@iblai/iblai-js 1.17.3 → 1.17.5
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.
|
@@ -87075,11 +87075,11 @@ function UsersTab({ tenant, currentPage, itemsPerPage, onInviteSuccess }) {
|
|
|
87075
87075
|
return 'Accepted';
|
|
87076
87076
|
};
|
|
87077
87077
|
const isFormValid = !emailError && debouncedEmail.trim().length > 0;
|
|
87078
|
-
return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "
|
|
87078
|
+
return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingInvitedUsers ? (
|
|
87079
87079
|
// Loading skeleton rows
|
|
87080
|
-
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-
|
|
87080
|
+
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
|
|
87081
87081
|
// Empty state
|
|
87082
|
-
jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-
|
|
87082
|
+
jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(Mail, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by inviting users above or uploading a CSV file" })] }) }) })) : (currentUsers.map((user) => (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center", children: jsx(Mail, { className: "h-4 w-4 text-blue-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: user.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(user.active, user.expired)}`, children: [user.active && !user.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !user.active && !user.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), user.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(user.active, user.expired)] }) })] }, user.id)))) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
|
|
87083
87083
|
}
|
|
87084
87084
|
|
|
87085
87085
|
function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermission = false, }) {
|
|
@@ -87446,15 +87446,15 @@ function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissio
|
|
|
87446
87446
|
else {
|
|
87447
87447
|
setSelectedCourses(selectedCourses.filter((c) => c.id !== course.id));
|
|
87448
87448
|
}
|
|
87449
|
-
} }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "
|
|
87449
|
+
} }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Course" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
|
|
87450
87450
|
// Loading skeleton rows
|
|
87451
|
-
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-
|
|
87451
|
+
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
|
|
87452
87452
|
// Empty state
|
|
87453
|
-
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-
|
|
87453
|
+
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(BookOpen, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No course invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and courses above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
|
|
87454
87454
|
var _a;
|
|
87455
|
-
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-
|
|
87455
|
+
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-green-100 flex items-center justify-center", children: jsx(BookOpen, { className: "h-4 w-4 text-green-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.course_id ||
|
|
87456
87456
|
((_a = invitation.course) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
87457
|
-
'Unknown Course' }) }), jsx("td", { className: "px-
|
|
87457
|
+
'Unknown Course' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
|
|
87458
87458
|
})) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
|
|
87459
87459
|
}
|
|
87460
87460
|
|
|
@@ -87823,15 +87823,15 @@ function ProgramsTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissi
|
|
|
87823
87823
|
else {
|
|
87824
87824
|
setSelectedPrograms(selectedPrograms.filter((p) => p.id !== program.id));
|
|
87825
87825
|
}
|
|
87826
|
-
} }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "
|
|
87826
|
+
} }), jsx("div", { className: "flex-1", children: jsx(Label$2, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label$2, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$1, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Program" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
|
|
87827
87827
|
// Loading skeleton rows
|
|
87828
|
-
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-
|
|
87828
|
+
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
|
|
87829
87829
|
// Empty state
|
|
87830
|
-
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-
|
|
87830
|
+
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(GraduationCap, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No program invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and programs above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
|
|
87831
87831
|
var _a;
|
|
87832
|
-
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-
|
|
87832
|
+
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-purple-100 flex items-center justify-center", children: jsx(GraduationCap, { className: "h-4 w-4 text-purple-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.program_key ||
|
|
87833
87833
|
((_a = invitation.program) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
87834
|
-
'Unknown Program' }) }), jsx("td", { className: "px-
|
|
87834
|
+
'Unknown Program' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
|
|
87835
87835
|
})) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
|
|
87836
87836
|
}
|
|
87837
87837
|
|
|
@@ -87916,7 +87916,7 @@ function InviteUserDialog({ tenant, onClose, isOpen, enableCatalogInvite = false
|
|
|
87916
87916
|
}
|
|
87917
87917
|
};
|
|
87918
87918
|
const headerContent = getHeaderContent();
|
|
87919
|
-
return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-
|
|
87919
|
+
return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-7xl w-[95vw] p-0 gap-0 mx-auto my-auto rounded-lg flex flex-col justify-between max-h-[90vh]", "aria-describedby": "invite-users-description", children: [jsxs(DialogHeader, { className: "p-4 pt-[30px] flex-shrink-0 border-b border-gray-200", children: [jsx(DialogTitle, { className: "text-lg font-medium text-gray-900 dark:text-gray-100", children: headerContent.title }), jsx(DialogDescription, { id: "invite-users-description", className: "text-sm text-gray-600 leading-relaxed", children: headerContent.description })] }), jsx("div", { className: "flex-grow overflow-y-auto scrollbar-hide p-2 sm:p-4 pb-20 max-h-[60vh]", children: enableCatalogInvite ? (jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [jsxs(TabsList, { className: "grid w-full grid-cols-3 mb-6", children: [jsxs(TabsTrigger, { value: "users", className: "flex items-center gap-2", children: [jsx(Users, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Users" })] }), jsxs(TabsTrigger, { value: "courses", className: "flex items-center gap-2", children: [jsx(BookOpen, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Courses" })] }), jsxs(TabsTrigger, { value: "programs", className: "flex items-center gap-2", children: [jsx(GraduationCap, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Programs" })] })] }), jsx(TabsContent, { value: "users", children: jsx(UsersTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess }) }), jsx(TabsContent, { value: "courses", children: jsx(CoursesTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) }), jsx(TabsContent, { value: "programs", children: jsx(ProgramsTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) })] })) : (jsx(UsersTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess })) }), currentData && currentData.count > 0 && (jsx("div", { className: "flex items-center justify-between border-t border-gray-200 px-3 sm:px-6 py-3 sm:py-4 bg-gray-50 flex-shrink-0", children: jsxs("div", { className: "flex flex-1 items-center justify-between", children: [jsx("div", { className: "hidden sm:block", children: jsxs("p", { className: "text-sm text-gray-700", children: ["Showing", ' ', jsx("span", { className: "font-medium", children: (currentPage - 1) * itemsPerPage + 1 }), " to", ' ', jsx("span", { className: "font-medium", children: Math.min(currentPage * itemsPerPage, currentData.count) }), ' ', "of ", jsx("span", { className: "font-medium", children: currentData.count }), " invites"] }) }), jsxs("div", { className: "flex items-center justify-center gap-1 sm:gap-2", children: [jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(1), disabled: currentPage === 1, "aria-label": "Go to first page", children: jsx(ChevronFirst, { className: "h-4 w-4" }) }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: [jsx(ChevronLeft, { className: "h-4 w-4 mr-1 sm:mr-0" }), jsx("span", { className: "sm:hidden", children: "Prev" })] }), jsxs("span", { className: "text-xs sm:text-sm text-gray-700 mx-1 sm:mx-2 px-2", children: [jsx("span", { className: "hidden sm:inline", children: "Page " }), currentPage, " ", jsx("span", { className: "hidden sm:inline", children: "of " }), jsx("span", { className: "inline sm:hidden", children: " / " }), totalPages] }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: [jsx("span", { className: "sm:hidden", children: "Next" }), jsx(ChevronRight, { className: "h-4 w-4 ml-1 sm:ml-0" })] }), jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(totalPages), disabled: currentPage === totalPages, "aria-label": "Go to last page", children: jsx(ChevronLast, { className: "h-4 w-4" }) })] })] }) }))] }) }) }));
|
|
87920
87920
|
}
|
|
87921
87921
|
|
|
87922
87922
|
function InvitedUsersDialog({ tenant, onClose, }) {
|
|
@@ -124782,11 +124782,11 @@ function UsersTab$1({ tenant, currentPage, itemsPerPage, onInviteSuccess }) {
|
|
|
124782
124782
|
return 'Accepted';
|
|
124783
124783
|
};
|
|
124784
124784
|
const isFormValid = !emailError && debouncedEmail.trim().length > 0;
|
|
124785
|
-
return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "
|
|
124785
|
+
return (jsxs("div", { className: "mt-0 space-y-6", children: [jsxs("div", { className: "space-y-4", children: [jsx("form", { onSubmit: handleSendInvite, className: "space-y-4", children: jsxs("div", { className: "flex gap-4 items-center sm:items-end flex-col sm:flex-row", children: [jsxs("div", { className: "relative flex-1 w-full", children: [jsx(Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" }), jsx(Input, { id: "email-invite", type: "email", placeholder: "Enter email to invite...", value: email, onChange: handleEmailChange, required: true, className: `pl-9 border-gray-300 focus:border-blue-500 focus:ring-blue-500 h-11 ${emailError ? 'border-red-500 focus:border-red-500' : ''}` })] }), jsxs("div", { className: "flex gap-2", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm", disabled: inviteSent || !isFormValid || isLoading, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent", disabled: isParsingCSV, asChild: !isParsingCSV, children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }) }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingInvitedUsers ? (
|
|
124786
124786
|
// Loading skeleton rows
|
|
124787
|
-
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-
|
|
124787
|
+
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
|
|
124788
124788
|
// Empty state
|
|
124789
|
-
jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-
|
|
124789
|
+
jsx("tr", { children: jsx("td", { colSpan: 2, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(Mail, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by inviting users above or uploading a CSV file" })] }) }) })) : (currentUsers.map((user) => (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center", children: jsx(Mail, { className: "h-4 w-4 text-blue-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: user.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(user.active, user.expired)}`, children: [user.active && !user.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !user.active && !user.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), user.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(user.active, user.expired)] }) })] }, user.id)))) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
|
|
124790
124790
|
}
|
|
124791
124791
|
|
|
124792
124792
|
function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermission = false, }) {
|
|
@@ -125153,15 +125153,15 @@ function CoursesTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissio
|
|
|
125153
125153
|
else {
|
|
125154
125154
|
setSelectedCourses(selectedCourses.filter((c) => c.id !== course.id));
|
|
125155
125155
|
}
|
|
125156
|
-
} }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "
|
|
125156
|
+
} }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `course-${course.id}`, className: "font-medium cursor-pointer text-sm", children: course.name }) })] }, course.id))), isFetchingCourses && courseCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedCourses.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Courses:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedCourses.map((course) => (jsxs("div", { className: "flex items-center gap-1 bg-green-100 text-green-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: course.name }), jsx("button", { type: "button", onClick: () => removeSelectedCourse(course.id), className: "ml-1 hover:bg-green-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, course.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Course" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
|
|
125157
125157
|
// Loading skeleton rows
|
|
125158
|
-
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-
|
|
125158
|
+
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
|
|
125159
125159
|
// Empty state
|
|
125160
|
-
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-
|
|
125160
|
+
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(BookOpen, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No course invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and courses above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
|
|
125161
125161
|
var _a;
|
|
125162
|
-
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-
|
|
125162
|
+
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-green-100 flex items-center justify-center", children: jsx(BookOpen, { className: "h-4 w-4 text-green-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.course_id ||
|
|
125163
125163
|
((_a = invitation.course) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
125164
|
-
'Unknown Course' }) }), jsx("td", { className: "px-
|
|
125164
|
+
'Unknown Course' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
|
|
125165
125165
|
})) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
|
|
125166
125166
|
}
|
|
125167
125167
|
|
|
@@ -125530,15 +125530,15 @@ function ProgramsTab({ tenant, currentPage, itemsPerPage, hasManageUsersPermissi
|
|
|
125530
125530
|
else {
|
|
125531
125531
|
setSelectedPrograms(selectedPrograms.filter((p) => p.id !== program.id));
|
|
125532
125532
|
}
|
|
125533
|
-
} }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "
|
|
125533
|
+
} }), jsx("div", { className: "flex-1", children: jsx(Label, { htmlFor: `program-${program.id}`, className: "font-medium cursor-pointer text-sm", children: program.name }) })] }, program.id))), isFetchingPrograms && programCurrentPage > 1 && (jsxs("div", { className: "p-3 text-sm text-gray-500 flex items-center justify-center gap-2", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading more..."] }))] })) })] }))] }), jsxs("div", { className: "flex gap-2 w-full lg:w-auto", children: [jsx(Button$1, { type: "submit", className: "gap-2 bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90 hover:text-white text-sm h-11 flex-1 lg:flex-none", disabled: inviteSent || !isFormValid, children: inviteSent ? (jsxs(Fragment$1, { children: [jsx(Check, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Invite Sent" }), jsx("span", { className: "sm:hidden", children: "Sent" })] })) : (jsxs(Fragment$1, { children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Send Invite" }), jsx("span", { className: "sm:hidden", children: "Send" })] })) }), jsxs("label", { className: isParsingCSV ? 'cursor-not-allowed' : 'cursor-pointer', children: [jsx(Button$1, { variant: "outline", size: "default", className: "gap-2 bg-transparent h-11", disabled: isParsingCSV, asChild: !isParsingCSV, type: "button", children: jsxs("span", { className: "flex items-center gap-2", children: [isParsingCSV ? (jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" })) : (jsx(Upload, { className: "h-4 w-4" })), jsx("span", { className: "hidden sm:inline", children: isParsingCSV ? 'Parsing...' : 'Upload CSV' }), jsx("span", { className: "sm:hidden", children: isParsingCSV ? '...' : 'CSV' })] }) }), jsx("input", { type: "file", accept: ".csv", onChange: handleFileUpload, className: "hidden", disabled: isParsingCSV })] })] })] }), selectedUsers.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Users:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedUsers.map((user) => (jsxs("div", { className: "flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: user.name || user.email || user.username }), jsx("button", { type: "button", onClick: () => removeSelectedUser(user.email), className: "ml-1 hover:bg-blue-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, user.email))) })] })), selectedPrograms.length > 0 && (jsxs("div", { className: "space-y-2", children: [jsx(Label, { className: "text-sm font-medium text-gray-700", children: "Selected Programs:" }), jsx("div", { className: "flex flex-wrap gap-2", children: selectedPrograms.map((program) => (jsxs("div", { className: "flex items-center gap-1 bg-purple-100 text-purple-800 px-2 py-1 rounded-full text-xs", children: [jsx("span", { children: program.name }), jsx("button", { type: "button", onClick: () => removeSelectedProgram(program.id), className: "ml-1 hover:bg-purple-200 rounded-full p-0.5", children: jsx(X$2, { className: "h-3 w-3" }) })] }, program.id))) })] }))] }), jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-700", children: [jsx("span", { children: "Need a template?" }), jsx(Button$1, { variant: "link", size: "sm", onClick: downloadTemplate, className: "p-0 h-auto text-blue-700 hover:text-blue-800", children: "Download CSV template" })] })] }), jsx("div", { className: "space-y-4", children: jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsx("div", { className: "min-w-[200px] align-middle", children: jsx("div", { className: "w-full", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[150px]", children: "Email" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[200px]", children: "Program" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 min-w-[80px]", children: "Status" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isLoadingData ? (
|
|
125534
125534
|
// Loading skeleton rows
|
|
125535
|
-
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-
|
|
125535
|
+
Array.from({ length: 5 }).map((_, index) => (jsxs("tr", { className: "animate-pulse", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-gray-200", "aria-hidden": "true" }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-32", "aria-hidden": "true" }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-40", "aria-hidden": "true" }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "h-5 bg-gray-200 rounded-full w-16", "aria-hidden": "true" }) })] }, `loading-${index}`)))) : currentUsers.length === 0 ? (
|
|
125536
125536
|
// Empty state
|
|
125537
|
-
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-
|
|
125537
|
+
jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-12 text-center", children: jsxs("div", { className: "flex flex-col items-center justify-center text-gray-500", children: [jsx(GraduationCap, { className: "h-12 w-12 mb-3 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm font-medium", children: "No program invitations yet" }), jsx("p", { className: "text-xs mt-1", children: "Start by selecting users and programs above or upload a CSV file" })] }) }) })) : (currentUsers.map((invitation) => {
|
|
125538
125538
|
var _a;
|
|
125539
|
-
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-
|
|
125539
|
+
return (jsxs("tr", { className: "hover:bg-gray-50 transition-colors duration-150", children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("div", { className: "flex items-center truncate max-w-[200px] sm:max-w-full", children: [jsx("div", { className: "flex-shrink-0 h-8 w-8", children: jsx("div", { className: "h-8 w-8 rounded-full bg-purple-100 flex items-center justify-center", children: jsx(GraduationCap, { className: "h-4 w-4 text-purple-600", "aria-hidden": "true" }) }) }), jsx("div", { className: "ml-3", children: jsx("div", { className: "text-sm font-medium text-gray-900", children: invitation.email || 'No email' }) })] }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsx("div", { className: "text-sm text-gray-900", children: invitation.program_key ||
|
|
125540
125540
|
((_a = invitation.program) === null || _a === void 0 ? void 0 : _a.name) ||
|
|
125541
|
-
'Unknown Program' }) }), jsx("td", { className: "px-
|
|
125541
|
+
'Unknown Program' }) }), jsx("td", { className: "px-6 py-4 whitespace-nowrap", children: jsxs("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(invitation.active, invitation.expired)}`, children: [invitation.active && !invitation.expired && (jsx(Clock, { className: "h-3 w-3 mr-1 text-blue-500", "aria-hidden": "true" })), !invitation.active && !invitation.expired && (jsx(CircleCheck, { className: "h-3 w-3 mr-1 text-green-700", "aria-hidden": "true" })), invitation.expired && (jsx(CircleX, { className: "h-3 w-3 mr-1 text-gray-500", "aria-hidden": "true" })), getStatusText(invitation.active, invitation.expired)] }) })] }, invitation.id));
|
|
125542
125542
|
})) })] }) }) }) }) }), isCSVEditorOpen && (jsx(CSVEditor, { csvData: parsedCSVData, onSave: handleCSVEditorSave, onCancel: handleCSVEditorCancel }))] }));
|
|
125543
125543
|
}
|
|
125544
125544
|
|
|
@@ -125623,7 +125623,7 @@ function InviteUserDialog({ tenant, onClose, isOpen, enableCatalogInvite = false
|
|
|
125623
125623
|
}
|
|
125624
125624
|
};
|
|
125625
125625
|
const headerContent = getHeaderContent();
|
|
125626
|
-
return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-
|
|
125626
|
+
return (jsx(Fragment$1, { children: jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { className: "sm:max-w-7xl w-[95vw] p-0 gap-0 mx-auto my-auto rounded-lg flex flex-col justify-between max-h-[90vh]", "aria-describedby": "invite-users-description", children: [jsxs(DialogHeader, { className: "p-4 pt-[30px] flex-shrink-0 border-b border-gray-200", children: [jsx(DialogTitle, { className: "text-lg font-medium text-gray-900 dark:text-gray-100", children: headerContent.title }), jsx(DialogDescription, { id: "invite-users-description", className: "text-sm text-gray-600 leading-relaxed", children: headerContent.description })] }), jsx("div", { className: "flex-grow overflow-y-auto scrollbar-hide p-2 sm:p-4 pb-20 max-h-[60vh]", children: enableCatalogInvite ? (jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [jsxs(TabsList, { className: "grid w-full grid-cols-3 mb-6", children: [jsxs(TabsTrigger, { value: "users", className: "flex items-center gap-2", children: [jsx(Users, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Users" })] }), jsxs(TabsTrigger, { value: "courses", className: "flex items-center gap-2", children: [jsx(BookOpen, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Courses" })] }), jsxs(TabsTrigger, { value: "programs", className: "flex items-center gap-2", children: [jsx(GraduationCap, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: "Programs" })] })] }), jsx(TabsContent, { value: "users", children: jsx(UsersTab$1, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess }) }), jsx(TabsContent, { value: "courses", children: jsx(CoursesTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) }), jsx(TabsContent, { value: "programs", children: jsx(ProgramsTab, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, hasManageUsersPermission: hasManageUsersPermission }) })] })) : (jsx(UsersTab$1, { tenant: tenant, currentPage: currentPage, itemsPerPage: itemsPerPage, onInviteSuccess: handleInviteSuccess })) }), currentData && currentData.count > 0 && (jsx("div", { className: "flex items-center justify-between border-t border-gray-200 px-3 sm:px-6 py-3 sm:py-4 bg-gray-50 flex-shrink-0", children: jsxs("div", { className: "flex flex-1 items-center justify-between", children: [jsx("div", { className: "hidden sm:block", children: jsxs("p", { className: "text-sm text-gray-700", children: ["Showing", ' ', jsx("span", { className: "font-medium", children: (currentPage - 1) * itemsPerPage + 1 }), " to", ' ', jsx("span", { className: "font-medium", children: Math.min(currentPage * itemsPerPage, currentData.count) }), ' ', "of ", jsx("span", { className: "font-medium", children: currentData.count }), " invites"] }) }), jsxs("div", { className: "flex items-center justify-center gap-1 sm:gap-2", children: [jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(1), disabled: currentPage === 1, "aria-label": "Go to first page", children: jsx(ChevronFirst, { className: "h-4 w-4" }) }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: [jsx(ChevronLeft, { className: "h-4 w-4 mr-1 sm:mr-0" }), jsx("span", { className: "sm:hidden", children: "Prev" })] }), jsxs("span", { className: "text-xs sm:text-sm text-gray-700 mx-1 sm:mx-2 px-2", children: [jsx("span", { className: "hidden sm:inline", children: "Page " }), currentPage, " ", jsx("span", { className: "hidden sm:inline", children: "of " }), jsx("span", { className: "inline sm:hidden", children: " / " }), totalPages] }), jsxs(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 px-2 sm:p-0 flex items-center justify-center rounded-md border-none sm:border-gray-300 hover:bg-gray-100 text-xs sm:text-sm bg-transparent", onClick: () => setCurrentPage(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: [jsx("span", { className: "sm:hidden", children: "Next" }), jsx(ChevronRight, { className: "h-4 w-4 ml-1 sm:ml-0" })] }), jsx(Button$1, { variant: "outline", size: "sm", className: "h-8 w-8 p-0 flex items-center justify-center rounded-md border-gray-300 hover:bg-gray-100 hidden sm:flex bg-transparent", onClick: () => setCurrentPage(totalPages), disabled: currentPage === totalPages, "aria-label": "Go to last page", children: jsx(ChevronLast, { className: "h-4 w-4" }) })] })] }) }))] }) }) }));
|
|
125627
125627
|
}
|
|
125628
125628
|
|
|
125629
125629
|
function InvitedUsersDialog({ tenant, onClose, }) {
|
|
@@ -198403,6 +198403,12 @@ function DeleteApiModal$1({ isOpen, onClose, apiKey, tenantKey }) {
|
|
|
198403
198403
|
return (jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: jsxs(DialogContent, { "aria-describedby": "delete-api-key-description", children: [jsx(DialogHeader, { children: jsx(DialogTitle, { className: "ibl-dialog-title", children: "Delete API Key" }) }), jsx("div", { className: "my-5", children: jsxs("p", { className: "text-sm text-[#646464]", children: ["Are you sure you want to delete the API Key with the name", ' ', jsx("span", { className: "font-bold italic", children: apiKey.name }), "? This action cannot be undone."] }) }), jsxs(DialogFooter, { className: "gap-3", children: [jsx(Button$1, { variant: "outline", onClick: onClose, children: "Cancel" }), jsx(Button$1, { className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", onClick: handleDeleteApiKey, disabled: isLoading, children: isLoading ? 'Deleting...' : 'Delete' })] })] }) }));
|
|
198404
198404
|
}
|
|
198405
198405
|
|
|
198406
|
+
/**
|
|
198407
|
+
* Blue informational banner used to describe a section, matching the RBAC
|
|
198408
|
+
* management tab styling (see `admin.tsx`).
|
|
198409
|
+
*/
|
|
198410
|
+
const InfoBanner = ({ icon, title, id, children, className }) => (jsxs("div", { className: `flex gap-3 items-center border rounded-lg p-4 bg-blue-50/60 border-blue-100 ${className !== null && className !== void 0 ? className : ''}`, children: [icon && (jsx("div", { className: "shrink-0 w-9 h-9 rounded-md flex items-center justify-center bg-blue-100 text-blue-600", children: icon })), jsxs("div", { className: "flex-1 min-w-0", children: [title && jsx("h3", { className: "text-sm font-semibold mb-1 text-blue-900", children: title }), jsx("p", { id: id, className: "text-sm text-gray-600 leading-relaxed", children: children })] })] }));
|
|
198411
|
+
|
|
198406
198412
|
function IntegrationAutogeneratedTab({ tenantKey }) {
|
|
198407
198413
|
const { data: apiKeys, isLoading: isApiKeysLoading } = useGetApiKeysQuery({
|
|
198408
198414
|
platformKey: tenantKey,
|
|
@@ -198414,7 +198420,7 @@ function IntegrationAutogeneratedTab({ tenantKey }) {
|
|
|
198414
198420
|
function openDeleteApiModal(apiKey) {
|
|
198415
198421
|
setApiKeyToDelete(apiKey);
|
|
198416
198422
|
}
|
|
198417
|
-
return (jsxs(Fragment$1, { children: [jsxs(
|
|
198423
|
+
return (jsxs(Fragment$1, { children: [jsxs("div", { className: "space-y-4", children: [jsx(InfoBanner, { icon: jsx(KeyRound, { className: "w-5 h-5" }), children: "These are authentication keys that you've generated for external applications to authenticate with your service. Keys are displayed only once when generated." }), jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Name" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Created" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Expires" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[50px]" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isApiKeysLoading ? (jsx("tr", { children: jsx("td", { colSpan: 4, className: "px-6 py-8 text-center text-sm text-gray-500", children: "Loading..." }) })) : (apiKeys === null || apiKeys === void 0 ? void 0 : apiKeys.length) === 0 ? (jsx("tr", { children: jsx("td", { colSpan: 4, className: "px-6 py-8 text-center text-sm text-gray-500", children: "No API keys found" }) })) : (apiKeys === null || apiKeys === void 0 ? void 0 : apiKeys.map((apiKey) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 whitespace-nowrap text-gray-900 dark:text-gray-100", children: apiKey.name }), jsx("td", { className: "px-6 py-4 whitespace-nowrap text-gray-600 dark:text-gray-300", children: apiKey.created ? format(apiKey.created, 'PPP') : 'N/A' }), jsx("td", { className: "px-6 py-4 whitespace-nowrap text-gray-600 dark:text-gray-300", children: apiKey.expires ? format(apiKey.expires, 'PPP') : 'N/A' }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer", onClick: () => openDeleteApiModal({ name: apiKey.name }), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, apiKey.name)))) })] }) })] }), apiKeyToDelete && (jsx(DeleteApiModal$1, { isOpen: !!apiKeyToDelete, onClose: closeDeleteApiModal, apiKey: apiKeyToDelete, tenantKey: tenantKey }))] }));
|
|
198418
198424
|
}
|
|
198419
198425
|
|
|
198420
198426
|
function ApiKeyModal$1({ isOpen, onClose, apiKey }) {
|
|
@@ -198799,23 +198805,23 @@ function IntegrationLLMsTab({ tenantKey }) {
|
|
|
198799
198805
|
toast.error('Failed to delete credential');
|
|
198800
198806
|
}
|
|
198801
198807
|
};
|
|
198802
|
-
return (jsxs(
|
|
198803
|
-
|
|
198804
|
-
|
|
198805
|
-
|
|
198806
|
-
|
|
198807
|
-
|
|
198808
|
-
|
|
198809
|
-
|
|
198810
|
-
|
|
198811
|
-
|
|
198812
|
-
|
|
198813
|
-
|
|
198814
|
-
|
|
198815
|
-
|
|
198816
|
-
|
|
198817
|
-
|
|
198818
|
-
|
|
198808
|
+
return (jsxs("div", { className: "space-y-4", children: [jsx(InfoBanner, { icon: jsx(Bot, { className: "w-5 h-5" }), children: "These are LLM keys from third-party services that you've configured for use with your application." }), jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm min-w-[600px]", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Name" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Key" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[50px]" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isMaskedCredentialsLoading ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "Loading..." }) })) : maskedCredentials.length === 0 ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "No LLM keys found" }) })) : (maskedCredentials.map((cred, idx) => {
|
|
198809
|
+
var _a, _b, _c;
|
|
198810
|
+
const provider = ((_a = cred.service_info) === null || _a === void 0 ? void 0 : _a.display_name) || cred.name;
|
|
198811
|
+
// Use logo from service_info only
|
|
198812
|
+
let logoUrl;
|
|
198813
|
+
let logoAlt;
|
|
198814
|
+
if ((_b = cred.service_info) === null || _b === void 0 ? void 0 : _b.logo) {
|
|
198815
|
+
logoUrl = cred.service_info.logo;
|
|
198816
|
+
logoAlt = cred.service_info.display_name || cred.service_info.name;
|
|
198817
|
+
}
|
|
198818
|
+
const isAzure = isAzureOpenAI(cred);
|
|
198819
|
+
const azureModels = isAzure ? getAzureModels(cred) : [];
|
|
198820
|
+
const isExpanded = expandedRows.has(cred.name);
|
|
198821
|
+
return (jsxs(React__default.Fragment, { children: [jsxs("tr", { children: [jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex items-center gap-2", children: [logoUrl ? (jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" })) : (jsx("span", { className: "text-lg", children: '🔑' })), jsx("span", { className: "font-normal text-gray-900 dark:text-gray-100", children: provider || cred.name }), isAzure && azureModels.length > 0 && (jsx("button", { type: "button", onClick: () => toggleRowExpansion(cred.name), className: "p-0.5 hover:bg-gray-100 rounded", children: isExpanded ? (jsx(ChevronUp, { className: "h-4 w-4 text-gray-500" })) : (jsx(ChevronDown, { className: "h-4 w-4 text-gray-500" })) }))] }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-900 dark:text-gray-100", children: isAzure ? (jsxs("span", { className: "text-xs text-gray-500", children: ["(", azureModels.length, " model", azureModels.length > 1 ? 's' : '', ")"] })) : (String((_c = cred === null || cred === void 0 ? void 0 : cred.value) === null || _c === void 0 ? void 0 : _c.key).slice(0, 15) || '') }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer mr-2", disabled: isDeletingIntegration || isDeletingCredential, onClick: () => handleDeleteCredential(cred.name, cred.platform, false), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }), isAzure &&
|
|
198822
|
+
isExpanded &&
|
|
198823
|
+
azureModels.map((model, modelIdx) => (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4 pl-12", children: jsx("span", { className: "text-sm text-gray-700", children: model.modelName.toLowerCase() }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-600", children: model.maskedKey.slice(0, 15) || '' }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer", disabled: isDeletingIntegration || isDeletingCredential, onClick: () => handleDeleteCredential(cred.name, cred.platform, false, model.modelName), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, `${cred.name}-${model.modelName}-${modelIdx}`)))] }, cred.name + idx));
|
|
198824
|
+
})) })] }) })] }));
|
|
198819
198825
|
}
|
|
198820
198826
|
|
|
198821
198827
|
// Dynamic schema based on selected provider
|
|
@@ -198938,7 +198944,7 @@ function CreateDataSourceModal({ isOpen, onClose, tenantKey, onSuccess }) {
|
|
|
198938
198944
|
} }, schemaField.name))) })), jsx(DialogFooter, { className: "justify-end", children: jsx(form.Subscribe, { selector: (state) => ({ canSubmit: state.canSubmit }), children: ({ canSubmit }) => (jsx(Button$1, { type: "submit", disabled: !canSubmit || isLoading || isIntegrationSchemaLoading, className: "bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: isLoading ? 'Submitting...' : 'Submit' })) }) })] })] }) }));
|
|
198939
198945
|
}
|
|
198940
198946
|
|
|
198941
|
-
function IntegrationDataSourcesTab({ tenantKey
|
|
198947
|
+
function IntegrationDataSourcesTab({ tenantKey }) {
|
|
198942
198948
|
// Fetch masked integration credentials from API
|
|
198943
198949
|
const { data: maskedCredentials = [], isLoading: isMaskedCredentialsLoading, refetch, } = useGetMaskedIntegrationCredentialsQuery({ org: tenantKey });
|
|
198944
198950
|
const [deleteIntegrationCredential, { isLoading: isDeletingIntegration }] = useDeleteIntegrationCredentialMutation();
|
|
@@ -198949,26 +198955,26 @@ function IntegrationDataSourcesTab({ tenantKey, }) {
|
|
|
198949
198955
|
platform_key: platformKey,
|
|
198950
198956
|
name,
|
|
198951
198957
|
}).unwrap();
|
|
198952
|
-
toast.success(
|
|
198958
|
+
toast.success('Data source credential deleted successfully');
|
|
198953
198959
|
refetch();
|
|
198954
198960
|
}
|
|
198955
198961
|
catch (error) {
|
|
198956
|
-
console.error(
|
|
198957
|
-
toast.error(
|
|
198962
|
+
console.error('Failed to delete credential:', error);
|
|
198963
|
+
toast.error('Failed to delete credential');
|
|
198958
198964
|
}
|
|
198959
198965
|
};
|
|
198960
|
-
return (jsxs(
|
|
198961
|
-
|
|
198962
|
-
|
|
198963
|
-
|
|
198964
|
-
|
|
198965
|
-
|
|
198966
|
-
|
|
198967
|
-
|
|
198968
|
-
|
|
198969
|
-
|
|
198970
|
-
|
|
198971
|
-
|
|
198966
|
+
return (jsxs("div", { className: "space-y-4", children: [jsx(InfoBanner, { icon: jsx(Database, { className: "w-5 h-5" }), children: "These are data source credentials from third-party services that you've configured for use with your application." }), jsx("div", { className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-x-auto", children: jsxs("table", { className: "w-full text-sm min-w-[600px]", children: [jsx("thead", { className: "bg-gray-50 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600", children: jsxs("tr", { children: [jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Name" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400", children: "Key" }), jsx("th", { className: "px-6 py-3 text-left font-medium text-gray-500 dark:text-gray-400 w-[50px]" })] }) }), jsx("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600", children: isMaskedCredentialsLoading ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "Loading..." }) })) : maskedCredentials.length === 0 ? (jsx("tr", { children: jsx("td", { colSpan: 3, className: "px-6 py-8 text-center text-sm text-gray-500", children: "No data source credentials found" }) })) : (maskedCredentials.map((cred, idx) => {
|
|
198967
|
+
var _a, _b, _c;
|
|
198968
|
+
const provider = ((_a = cred.service_info) === null || _a === void 0 ? void 0 : _a.display_name) || cred.name;
|
|
198969
|
+
// Use logo from service_info only
|
|
198970
|
+
let logoUrl;
|
|
198971
|
+
let logoAlt;
|
|
198972
|
+
if ((_b = cred.service_info) === null || _b === void 0 ? void 0 : _b.logo) {
|
|
198973
|
+
logoUrl = cred.service_info.logo;
|
|
198974
|
+
logoAlt = cred.service_info.display_name || cred.service_info.name;
|
|
198975
|
+
}
|
|
198976
|
+
return (jsxs("tr", { children: [jsx("td", { className: "px-6 py-4", children: jsxs("div", { className: "flex items-center gap-2", children: [logoUrl ? (jsx("img", { src: logoUrl, alt: logoAlt || provider || cred.name, className: "w-6 h-6 rounded-sm object-contain" })) : (jsx("span", { className: "text-lg", children: '🔑' })), jsx("span", { className: "font-normal text-gray-900 dark:text-gray-100", children: provider || cred.name })] }) }), jsx("td", { className: "px-6 py-4 font-mono text-sm text-gray-900 dark:text-gray-100", children: String((_c = cred === null || cred === void 0 ? void 0 : cred.value) === null || _c === void 0 ? void 0 : _c.key).slice(0, 15) || '' }), jsx("td", { className: "px-6 py-4", children: jsx(Button$1, { variant: "ghost", size: "sm", className: "cursor-pointer mr-2", disabled: isDeletingIntegration, onClick: () => handleDeleteCredential(cred.name, cred.platform), children: jsx(Trash, { className: "h-4 w-4" }) }) })] }, cred.name + idx));
|
|
198977
|
+
})) })] }) })] }));
|
|
198972
198978
|
}
|
|
198973
198979
|
|
|
198974
198980
|
function IntegrationsTab({ tenantKey, username, }) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iblai/iblai-js",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.5",
|
|
4
4
|
"description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
"winston": "3.19.0",
|
|
69
69
|
"@iblai/data-layer": "1.7.0",
|
|
70
70
|
"@iblai/mcp": "1.5.3",
|
|
71
|
-
"@iblai/web-
|
|
72
|
-
"@iblai/web-
|
|
71
|
+
"@iblai/web-containers": "1.8.6",
|
|
72
|
+
"@iblai/web-utils": "1.10.5"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"@radix-ui/react-dialog": "^1.1.7",
|