@iblai/iblai-js 1.21.1 → 1.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -138371,8 +138371,7 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
138371
138371
  const isChatPrivacyEnabled = !!(chatPrivacyConfig === null || chatPrivacyConfig === void 0 ? void 0 : chatPrivacyConfig.allow_user_chat_privacy_control);
138372
138372
  const currentTenant = tenants.find((t) => t.key === tenant);
138373
138373
  const isPurchasesEnabled = currentTenant === null || currentTenant === void 0 ? void 0 : currentTenant.enable_monetization;
138374
- const normalizedSPA = currentSPA.toLowerCase();
138375
- const isGradebookEnabled = normalizedSPA.includes('skills') || normalizedSPA.includes('lms');
138374
+ const isGradebookEnabled = customization.showGradebookTab;
138376
138375
  const isReadOnly = useIsProfilePreview(username);
138377
138376
  const baseTabs = [
138378
138377
  { id: 'basic', label: t('profileIndex.tabBasic'), renderIcon: renderLucideIcon(User) },
@@ -140318,7 +140317,7 @@ const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffs
140318
140317
  });
140319
140318
  PopoverContent.displayName = Content2$2.displayName;
140320
140319
 
140321
- function UsersTab({ tenant, onInviteClick, currentSpa, }) {
140320
+ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false, }) {
140322
140321
  const t = useT();
140323
140322
  const dispatch = useDispatch();
140324
140323
  const [page, setPage] = useState(1);
@@ -140504,7 +140503,9 @@ function UsersTab({ tenant, onInviteClick, currentSpa, }) {
140504
140503
  })] }) })] }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsx(Switch, { checked: user.active, onCheckedChange: (checked) => handleUserStatusChange(user, checked), disabled: updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), "aria-label": t('tabsUserstab.toggleStatusAriaLabel', { name: user.name }), className: "cursor-pointer data-[state=checked]:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50" }) })] }, index))), (!userData || userData.length === 0) && (jsx("tr", { children: jsx("td", { colSpan: 5, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsUserstab.noUsersFound') }) }))] })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (_page) => handlePageChange(_page), totalCount: users === null || users === void 0 ? void 0 : users.count, itemsPerPage: 10, itemLabel: "users" })] })), selectedUser && (jsx(Dialog, { open: !!selectedUser, onOpenChange: (open) => {
140505
140504
  if (!open)
140506
140505
  setSelectedUser(null);
140507
- }, children: jsxs(DialogContent, { autoFocus: false, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenant, tenants: [], username: selectedUser.username, isAdmin: selectedUser.is_admin, currentSPA: currentSpa, onClose: () => setSelectedUser(null) })] }) }))] }));
140506
+ }, children: jsxs(DialogContent, { autoFocus: false, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenant, tenants: [], username: selectedUser.username, isAdmin: selectedUser.is_admin, currentSPA: currentSpa, onClose: () => setSelectedUser(null), customization: {
140507
+ showGradebookTab: showGradebookTab,
140508
+ } })] }) }))] }));
140508
140509
  }
140509
140510
 
140510
140511
  // Permission options for teams access
@@ -142070,9 +142071,9 @@ const TabDescription = ({ icon, title, children }) => {
142070
142071
  const [expanded, setExpanded] = useState(false);
142071
142072
  return (jsxs("div", { className: "flex gap-3 items-start border rounded-lg p-4 bg-blue-50/60 border-blue-100", children: [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: [jsx("h3", { className: "text-sm font-semibold mb-1 text-blue-900 hidden sm:block", children: title }), jsx("p", { className: `text-sm text-gray-600 leading-relaxed sm:line-clamp-none! ${expanded ? '' : 'line-clamp-2'}`, children: children }), jsx("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 text-xs font-medium text-blue-700 hover:text-blue-800 sm:hidden", children: expanded ? t('profileAdmin.readLess') : t('profileAdmin.readMore') })] })] }));
142072
142073
  };
142073
- const Admin = ({ tenant, onInviteClick, hasUserTabPermission = false, hasGroupsTabPermission = false, hasRolesTabPermission = false, hasPoliciesTabPermission = false, hasTeamsTabPermission = false, hasAlertsTabPermission = false, hasInviteUserPermission = false, hasCreateTeamPermission = false, onLoadGroupPermissions, rbacPermissions = {}, enableRbac = false, currentSpa, }) => {
142074
+ const Admin = ({ tenant, onInviteClick, hasUserTabPermission = false, hasGroupsTabPermission = false, hasRolesTabPermission = false, hasPoliciesTabPermission = false, hasTeamsTabPermission = false, hasAlertsTabPermission = false, hasInviteUserPermission = false, hasCreateTeamPermission = false, onLoadGroupPermissions, rbacPermissions = {}, enableRbac = false, showGradebookTab = false, currentSpa, }) => {
142074
142075
  const t = useT();
142075
- return (jsx("div", { className: "border border-gray-200 rounded-lg p-6", children: jsxs(Tabs, { defaultValue: "users", "aria-label": t('profileAdmin.rbacManagementTabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('profileAdmin.managementTabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [hasUserTabPermission && (jsx(TabsTrigger, { value: "users", children: t('profileAdmin.usersTab') })), hasGroupsTabPermission && (jsx(TabsTrigger, { value: "groups", children: t('profileAdmin.groupsTab') })), hasRolesTabPermission && (jsx(TabsTrigger, { value: "roles", children: t('profileAdmin.rolesTab') })), hasPoliciesTabPermission && (jsx(TabsTrigger, { value: "policies", children: t('profileAdmin.policiesTab') })), hasTeamsTabPermission && (jsx(TabsTrigger, { value: "teams", children: t('profileAdmin.teamsTab') })), hasAlertsTabPermission && (jsx(TabsTrigger, { value: "alerts", children: t('profileAdmin.alertsTab') }))] }), hasUserTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "users", children: [jsx(TabDescription, { icon: jsx(Users, { className: "w-5 h-5" }), title: t('profileAdmin.usersTab'), children: t('profileAdmin.usersDescription') }), jsx(UsersTab, { tenant: tenant, onInviteClick: onInviteClick, currentSpa: currentSpa })] })), hasGroupsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "groups", children: [jsx(TabDescription, { icon: jsx(UsersRound, { className: "w-5 h-5" }), title: t('profileAdmin.groupsTab'), children: t('profileAdmin.groupsDescription') }), jsx(GroupsTab, { tenant: tenant })] })), hasRolesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "roles", children: [jsx(TabDescription, { icon: jsx(UserCog, { className: "w-5 h-5" }), title: t('profileAdmin.rolesTab'), children: t('profileAdmin.rolesDescription') }), jsx(RolesTab, { tenant: tenant })] })), hasPoliciesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "policies", children: [jsx(TabDescription, { icon: jsx(ScrollText, { className: "w-5 h-5" }), title: t('profileAdmin.policiesTab'), children: t('profileAdmin.policiesDescription') }), jsx(PoliciesTab, { tenant: tenant })] })), hasTeamsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "teams", children: [jsx(TabDescription, { icon: jsx(Shield, { className: "w-5 h-5" }), title: t('profileAdmin.teamsTab'), children: t('profileAdmin.teamsDescription') }), jsx(GroupsTab, { tenant: tenant, isTeam: true, onInviteClick: onInviteClick, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, rbacPermissions: rbacPermissions, enableRbac: enableRbac })] })), hasAlertsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "alerts", children: [jsx(TabDescription, { icon: jsx(BellRing, { className: "w-5 h-5" }), title: t('profileAdmin.alertsTab'), children: t('profileAdmin.alertsDescription') }), jsx(AlertsTab$1, { tenant: tenant })] }))] }) }));
142076
+ return (jsx("div", { className: "border border-gray-200 rounded-lg p-6", children: jsxs(Tabs, { defaultValue: "users", "aria-label": t('profileAdmin.rbacManagementTabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('profileAdmin.managementTabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [hasUserTabPermission && (jsx(TabsTrigger, { value: "users", children: t('profileAdmin.usersTab') })), hasGroupsTabPermission && (jsx(TabsTrigger, { value: "groups", children: t('profileAdmin.groupsTab') })), hasRolesTabPermission && (jsx(TabsTrigger, { value: "roles", children: t('profileAdmin.rolesTab') })), hasPoliciesTabPermission && (jsx(TabsTrigger, { value: "policies", children: t('profileAdmin.policiesTab') })), hasTeamsTabPermission && (jsx(TabsTrigger, { value: "teams", children: t('profileAdmin.teamsTab') })), hasAlertsTabPermission && (jsx(TabsTrigger, { value: "alerts", children: t('profileAdmin.alertsTab') }))] }), hasUserTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "users", children: [jsx(TabDescription, { icon: jsx(Users, { className: "w-5 h-5" }), title: t('profileAdmin.usersTab'), children: t('profileAdmin.usersDescription') }), jsx(UsersTab, { tenant: tenant, onInviteClick: onInviteClick, currentSpa: currentSpa, showGradebookTab: showGradebookTab })] })), hasGroupsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "groups", children: [jsx(TabDescription, { icon: jsx(UsersRound, { className: "w-5 h-5" }), title: t('profileAdmin.groupsTab'), children: t('profileAdmin.groupsDescription') }), jsx(GroupsTab, { tenant: tenant })] })), hasRolesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "roles", children: [jsx(TabDescription, { icon: jsx(UserCog, { className: "w-5 h-5" }), title: t('profileAdmin.rolesTab'), children: t('profileAdmin.rolesDescription') }), jsx(RolesTab, { tenant: tenant })] })), hasPoliciesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "policies", children: [jsx(TabDescription, { icon: jsx(ScrollText, { className: "w-5 h-5" }), title: t('profileAdmin.policiesTab'), children: t('profileAdmin.policiesDescription') }), jsx(PoliciesTab, { tenant: tenant })] })), hasTeamsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "teams", children: [jsx(TabDescription, { icon: jsx(Shield, { className: "w-5 h-5" }), title: t('profileAdmin.teamsTab'), children: t('profileAdmin.teamsDescription') }), jsx(GroupsTab, { tenant: tenant, isTeam: true, onInviteClick: onInviteClick, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, rbacPermissions: rbacPermissions, enableRbac: enableRbac })] })), hasAlertsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "alerts", children: [jsx(TabDescription, { icon: jsx(BellRing, { className: "w-5 h-5" }), title: t('profileAdmin.alertsTab'), children: t('profileAdmin.alertsDescription') }), jsx(AlertsTab$1, { tenant: tenant })] }))] }) }));
142076
142077
  };
142077
142078
 
142078
142079
  function DeleteApiModal({ isOpen, onClose, apiKey, tenantKey }) {
@@ -173197,8 +173197,7 @@ function Profile({ tenant, username, tenants, onClose, customization = {}, isAdm
173197
173197
  const isChatPrivacyEnabled = !!(chatPrivacyConfig === null || chatPrivacyConfig === void 0 ? void 0 : chatPrivacyConfig.allow_user_chat_privacy_control);
173198
173198
  const currentTenant = tenants.find((t) => t.key === tenant);
173199
173199
  const isPurchasesEnabled = currentTenant === null || currentTenant === void 0 ? void 0 : currentTenant.enable_monetization;
173200
- const normalizedSPA = currentSPA.toLowerCase();
173201
- const isGradebookEnabled = normalizedSPA.includes('skills') || normalizedSPA.includes('lms');
173200
+ const isGradebookEnabled = customization.showGradebookTab;
173202
173201
  const isReadOnly = useIsProfilePreview(username);
173203
173202
  const baseTabs = [
173204
173203
  { id: 'basic', label: t('profileIndex.tabBasic'), renderIcon: renderLucideIcon(User) },
@@ -175144,7 +175143,7 @@ const PopoverContent = React.forwardRef(({ className, align = 'center', sideOffs
175144
175143
  });
175145
175144
  PopoverContent.displayName = Content2.displayName;
175146
175145
 
175147
- function UsersTab({ tenant, onInviteClick, currentSpa, }) {
175146
+ function UsersTab({ tenant, onInviteClick, currentSpa, showGradebookTab = false, }) {
175148
175147
  const t = useT();
175149
175148
  const dispatch = useDispatch();
175150
175149
  const [page, setPage] = useState(1);
@@ -175330,7 +175329,9 @@ function UsersTab({ tenant, onInviteClick, currentSpa, }) {
175330
175329
  })] }) })] }) }), jsx("td", { className: "px-6 py-4", onClick: (e) => e.stopPropagation(), children: jsx(Switch, { checked: user.active, onCheckedChange: (checked) => handleUserStatusChange(user, checked), disabled: updatingUserIds.has(user === null || user === void 0 ? void 0 : user.user_id), "aria-label": t('tabsUserstab.toggleStatusAriaLabel', { name: user.name }), className: "cursor-pointer data-[state=checked]:bg-blue-500 disabled:cursor-not-allowed disabled:opacity-50" }) })] }, index))), (!userData || userData.length === 0) && (jsx("tr", { children: jsx("td", { colSpan: 5, className: "px-6 py-8 text-center text-gray-500 dark:text-gray-400", children: t('tabsUserstab.noUsersFound') }) }))] })] }) }), jsx(AdvancedPagination, { variant: "footer", className: "-mx-6 -mb-6 mt-4 rounded-b-lg", totalPages: totalPages, currentPage: page, onPageChange: (_page) => handlePageChange(_page), totalCount: users === null || users === void 0 ? void 0 : users.count, itemsPerPage: 10, itemLabel: "users" })] })), selectedUser && (jsx(Dialog, { open: !!selectedUser, onOpenChange: (open) => {
175331
175330
  if (!open)
175332
175331
  setSelectedUser(null);
175333
- }, children: jsxs(DialogContent, { autoFocus: false, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenant, tenants: [], username: selectedUser.username, isAdmin: selectedUser.is_admin, currentSPA: currentSpa, onClose: () => setSelectedUser(null) })] }) }))] }));
175332
+ }, children: jsxs(DialogContent, { autoFocus: false, className: "max-w-7xl w-[85vw] p-0 gap-0 overflow-hidden bg-white profile-component-dialog", style: { height: '85vh', display: 'flex', flexDirection: 'column' }, children: [jsx(DialogTitle, { className: "sr-only", children: t('tabsUserstab.profileDialogTitle') }), jsx(DialogDescription, { className: "sr-only", children: t('tabsUserstab.profileDialogDescription') }), jsx(Profile, { tenant: tenant, tenants: [], username: selectedUser.username, isAdmin: selectedUser.is_admin, currentSPA: currentSpa, onClose: () => setSelectedUser(null), customization: {
175333
+ showGradebookTab: showGradebookTab,
175334
+ } })] }) }))] }));
175334
175335
  }
175335
175336
 
175336
175337
  // Permission options for teams access
@@ -176896,9 +176897,9 @@ const TabDescription = ({ icon, title, children }) => {
176896
176897
  const [expanded, setExpanded] = useState(false);
176897
176898
  return (jsxs("div", { className: "flex gap-3 items-start border rounded-lg p-4 bg-blue-50/60 border-blue-100", children: [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: [jsx("h3", { className: "text-sm font-semibold mb-1 text-blue-900 hidden sm:block", children: title }), jsx("p", { className: `text-sm text-gray-600 leading-relaxed sm:line-clamp-none! ${expanded ? '' : 'line-clamp-2'}`, children: children }), jsx("button", { type: "button", onClick: () => setExpanded((prev) => !prev), className: "mt-1 text-xs font-medium text-blue-700 hover:text-blue-800 sm:hidden", children: expanded ? t('profileAdmin.readLess') : t('profileAdmin.readMore') })] })] }));
176898
176899
  };
176899
- const Admin = ({ tenant, onInviteClick, hasUserTabPermission = false, hasGroupsTabPermission = false, hasRolesTabPermission = false, hasPoliciesTabPermission = false, hasTeamsTabPermission = false, hasAlertsTabPermission = false, hasInviteUserPermission = false, hasCreateTeamPermission = false, onLoadGroupPermissions, rbacPermissions = {}, enableRbac = false, currentSpa, }) => {
176900
+ const Admin = ({ tenant, onInviteClick, hasUserTabPermission = false, hasGroupsTabPermission = false, hasRolesTabPermission = false, hasPoliciesTabPermission = false, hasTeamsTabPermission = false, hasAlertsTabPermission = false, hasInviteUserPermission = false, hasCreateTeamPermission = false, onLoadGroupPermissions, rbacPermissions = {}, enableRbac = false, showGradebookTab = false, currentSpa, }) => {
176900
176901
  const t = useT();
176901
- return (jsx("div", { className: "border border-gray-200 rounded-lg p-6", children: jsxs(Tabs, { defaultValue: "users", "aria-label": t('profileAdmin.rbacManagementTabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('profileAdmin.managementTabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [hasUserTabPermission && (jsx(TabsTrigger, { value: "users", children: t('profileAdmin.usersTab') })), hasGroupsTabPermission && (jsx(TabsTrigger, { value: "groups", children: t('profileAdmin.groupsTab') })), hasRolesTabPermission && (jsx(TabsTrigger, { value: "roles", children: t('profileAdmin.rolesTab') })), hasPoliciesTabPermission && (jsx(TabsTrigger, { value: "policies", children: t('profileAdmin.policiesTab') })), hasTeamsTabPermission && (jsx(TabsTrigger, { value: "teams", children: t('profileAdmin.teamsTab') })), hasAlertsTabPermission && (jsx(TabsTrigger, { value: "alerts", children: t('profileAdmin.alertsTab') }))] }), hasUserTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "users", children: [jsx(TabDescription, { icon: jsx(Users, { className: "w-5 h-5" }), title: t('profileAdmin.usersTab'), children: t('profileAdmin.usersDescription') }), jsx(UsersTab, { tenant: tenant, onInviteClick: onInviteClick, currentSpa: currentSpa })] })), hasGroupsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "groups", children: [jsx(TabDescription, { icon: jsx(UsersRound, { className: "w-5 h-5" }), title: t('profileAdmin.groupsTab'), children: t('profileAdmin.groupsDescription') }), jsx(GroupsTab, { tenant: tenant })] })), hasRolesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "roles", children: [jsx(TabDescription, { icon: jsx(UserCog, { className: "w-5 h-5" }), title: t('profileAdmin.rolesTab'), children: t('profileAdmin.rolesDescription') }), jsx(RolesTab, { tenant: tenant })] })), hasPoliciesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "policies", children: [jsx(TabDescription, { icon: jsx(ScrollText, { className: "w-5 h-5" }), title: t('profileAdmin.policiesTab'), children: t('profileAdmin.policiesDescription') }), jsx(PoliciesTab, { tenant: tenant })] })), hasTeamsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "teams", children: [jsx(TabDescription, { icon: jsx(Shield, { className: "w-5 h-5" }), title: t('profileAdmin.teamsTab'), children: t('profileAdmin.teamsDescription') }), jsx(GroupsTab, { tenant: tenant, isTeam: true, onInviteClick: onInviteClick, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, rbacPermissions: rbacPermissions, enableRbac: enableRbac })] })), hasAlertsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "alerts", children: [jsx(TabDescription, { icon: jsx(BellRing, { className: "w-5 h-5" }), title: t('profileAdmin.alertsTab'), children: t('profileAdmin.alertsDescription') }), jsx(AlertsTab, { tenant: tenant })] }))] }) }));
176902
+ return (jsx("div", { className: "border border-gray-200 rounded-lg p-6", children: jsxs(Tabs, { defaultValue: "users", "aria-label": t('profileAdmin.rbacManagementTabsAriaLabel'), children: [jsxs(TabsList, { "aria-label": t('profileAdmin.managementTabsAriaLabel'), className: "max-w-full overflow-x-auto justify-start px-1", children: [hasUserTabPermission && (jsx(TabsTrigger, { value: "users", children: t('profileAdmin.usersTab') })), hasGroupsTabPermission && (jsx(TabsTrigger, { value: "groups", children: t('profileAdmin.groupsTab') })), hasRolesTabPermission && (jsx(TabsTrigger, { value: "roles", children: t('profileAdmin.rolesTab') })), hasPoliciesTabPermission && (jsx(TabsTrigger, { value: "policies", children: t('profileAdmin.policiesTab') })), hasTeamsTabPermission && (jsx(TabsTrigger, { value: "teams", children: t('profileAdmin.teamsTab') })), hasAlertsTabPermission && (jsx(TabsTrigger, { value: "alerts", children: t('profileAdmin.alertsTab') }))] }), hasUserTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "users", children: [jsx(TabDescription, { icon: jsx(Users, { className: "w-5 h-5" }), title: t('profileAdmin.usersTab'), children: t('profileAdmin.usersDescription') }), jsx(UsersTab, { tenant: tenant, onInviteClick: onInviteClick, currentSpa: currentSpa, showGradebookTab: showGradebookTab })] })), hasGroupsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "groups", children: [jsx(TabDescription, { icon: jsx(UsersRound, { className: "w-5 h-5" }), title: t('profileAdmin.groupsTab'), children: t('profileAdmin.groupsDescription') }), jsx(GroupsTab, { tenant: tenant })] })), hasRolesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "roles", children: [jsx(TabDescription, { icon: jsx(UserCog, { className: "w-5 h-5" }), title: t('profileAdmin.rolesTab'), children: t('profileAdmin.rolesDescription') }), jsx(RolesTab, { tenant: tenant })] })), hasPoliciesTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "policies", children: [jsx(TabDescription, { icon: jsx(ScrollText, { className: "w-5 h-5" }), title: t('profileAdmin.policiesTab'), children: t('profileAdmin.policiesDescription') }), jsx(PoliciesTab, { tenant: tenant })] })), hasTeamsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "teams", children: [jsx(TabDescription, { icon: jsx(Shield, { className: "w-5 h-5" }), title: t('profileAdmin.teamsTab'), children: t('profileAdmin.teamsDescription') }), jsx(GroupsTab, { tenant: tenant, isTeam: true, onInviteClick: onInviteClick, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, rbacPermissions: rbacPermissions, enableRbac: enableRbac })] })), hasAlertsTabPermission && (jsxs(TabsContent, { className: "mt-4", value: "alerts", children: [jsx(TabDescription, { icon: jsx(BellRing, { className: "w-5 h-5" }), title: t('profileAdmin.alertsTab'), children: t('profileAdmin.alertsDescription') }), jsx(AlertsTab, { tenant: tenant })] }))] }) }));
176902
176903
  };
176903
176904
 
176904
176905
  function DeleteApiModal$1({ isOpen, onClose, apiKey, tenantKey }) {
@@ -252133,7 +252134,7 @@ function OrganizationTab({ platformKey, setOrganizationLogoFromOutside, tenant,
252133
252134
  }, className: "hidden" })] })] })] })] }));
252134
252135
  }
252135
252136
 
252136
- function Account({ tenant, tenants = [], username, onInviteClick, email, mainPlatformKey, userActiveApp = null, showPlatformName = false, isAdmin = false, targetTab = 'basic', currentPlan: _currentPlan = '', currentSPA = '', authURL, onTenantUpdate, currentPlatformBaseDomain = '', enableRbac = false, rbacPermissions = {}, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', enableSupportPhone, }) {
252137
+ function Account({ tenant, tenants = [], username, onInviteClick, email, mainPlatformKey, userActiveApp = null, showPlatformName = false, isAdmin = false, targetTab = 'basic', currentPlan: _currentPlan = '', currentSPA = '', authURL, onTenantUpdate, currentPlatformBaseDomain = '', enableRbac = false, rbacPermissions = {}, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', enableSupportPhone, showGradebookTab = false, }) {
252137
252138
  const t = useT();
252138
252139
  const currentTenant = tenants.find((ten) => ten.key === tenant);
252139
252140
  const hasMonetizationPermission = checkRbacPermission(rbacPermissions, `/platforms/${tenant}/#can_sell_items`, enableRbac);
@@ -252229,10 +252230,10 @@ function Account({ tenant, tenants = [], username, onInviteClick, email, mainPla
252229
252230
  : 'text-gray-600 hover:bg-gray-50'}`, children: [jsx(CreditCard, { className: "h-4 w-4" }), jsx("span", { className: "hidden sm:inline", children: t('profileAccount.tabBilling') }), jsx("span", { className: "sm:hidden", children: t('profileAccount.tabBilling') })] }, 'billing'))] }) }) }), jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", style: { height: '100%' }, children: [jsxs("div", { className: "hidden lg:block flex-shrink-0 p-6 border-b border-gray-200 bg-white dark:bg-gray-900", children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2 capitalize", children: activeTab }), jsxs("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: [activeTab === 'management' && t('profileAccount.descManagement'), activeTab === 'organization' && t('profileAccount.descOrganization'), activeTab === 'integrations' && t('profileAccount.descIntegrations'), activeTab === 'billing' && t('profileAccount.descBilling'), activeTab === 'monetization' && t('profileAccount.descMonetization'), activeTab === 'advanced' && t('profileAccount.descAdvanced')] })] }), jsxs("div", { className: "flex-1 p-6 space-y-6", style: {
252230
252231
  overflowY: 'auto',
252231
252232
  overflowX: 'hidden',
252232
- }, children: [jsxs("div", { className: "lg:hidden mb-6", children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2 capitalize", children: activeTab }), jsxs("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: [activeTab === 'basic' && t('profileAccount.descBasic'), activeTab === 'social' && t('profileAccount.descSocial'), activeTab === 'security' && t('profileAccount.descSecurity'), activeTab === 'management' && t('profileAccount.descManagement'), activeTab === 'organization' && t('profileAccount.descOrganization'), activeTab === 'monetization' && t('profileAccount.descMonetization'), activeTab === 'advanced' && t('profileAccount.descAdvanced')] })] }), activeTab === 'management' && hasManagementPermissions && (jsx(Admin, { onInviteClick: onInviteClick, tenant: tenant, currentSpa: currentSPA, hasUserTabPermission: hasUserTabPermission, hasGroupsTabPermission: hasGroupsTabPermission, hasPoliciesTabPermission: hasPoliciesTabPermission, hasRolesTabPermission: hasRolesTabPermission, hasTeamsTabPermission: hasTeamsTabPermission, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, hasAlertsTabPermission: hasAlertsTabPermission, rbacPermissions: rbacPermissions, enableRbac: enableRbac })), activeTab === 'organization' && (jsx(OrganizationTab, { platformKey: tenant, tenant: tenants.find((ten) => ten.key === tenant), onTenantUpdate: onTenantUpdate, setOrganizationLogoFromOutside: setOrganizationLogo, defaultSupportPhone: defaultSupportPhone, enableSupportPhone: enableSupportPhone })), activeTab === 'integrations' && (jsx(IntegrationsTab, { tenantKey: tenant, username: username })), activeTab === 'billing' && (jsx(BillingTab, { tenant: tenant, userActiveApp: userActiveApp, username: username, currentUserEmail: email, mainPlatformKey: mainPlatformKey })), activeTab === 'monetization' && (jsx(MonetizationTab, { platformKey: tenant, authURL: authURL })), activeTab === 'advanced' && (jsx(AdvancedTab, { platformKey: tenant, currentSPA: currentSPA, username: username, authURL: authURL, currentPlatformBaseDomain: currentPlatformBaseDomain }))] })] }), jsx(ToastProvider, {})] }));
252233
+ }, children: [jsxs("div", { className: "lg:hidden mb-6", children: [jsx("h3", { className: "text-lg font-medium text-gray-900 dark:text-gray-100 mb-2 capitalize", children: activeTab }), jsxs("p", { className: "text-gray-600 dark:text-gray-400 text-sm", children: [activeTab === 'basic' && t('profileAccount.descBasic'), activeTab === 'social' && t('profileAccount.descSocial'), activeTab === 'security' && t('profileAccount.descSecurity'), activeTab === 'management' && t('profileAccount.descManagement'), activeTab === 'organization' && t('profileAccount.descOrganization'), activeTab === 'monetization' && t('profileAccount.descMonetization'), activeTab === 'advanced' && t('profileAccount.descAdvanced')] })] }), activeTab === 'management' && hasManagementPermissions && (jsx(Admin, { onInviteClick: onInviteClick, tenant: tenant, currentSpa: currentSPA, hasUserTabPermission: hasUserTabPermission, hasGroupsTabPermission: hasGroupsTabPermission, hasPoliciesTabPermission: hasPoliciesTabPermission, hasRolesTabPermission: hasRolesTabPermission, hasTeamsTabPermission: hasTeamsTabPermission, hasInviteUserPermission: hasInviteUserPermission, hasCreateTeamPermission: hasCreateTeamPermission, onLoadGroupPermissions: onLoadGroupPermissions, hasAlertsTabPermission: hasAlertsTabPermission, rbacPermissions: rbacPermissions, enableRbac: enableRbac, showGradebookTab: showGradebookTab })), activeTab === 'organization' && (jsx(OrganizationTab, { platformKey: tenant, tenant: tenants.find((ten) => ten.key === tenant), onTenantUpdate: onTenantUpdate, setOrganizationLogoFromOutside: setOrganizationLogo, defaultSupportPhone: defaultSupportPhone, enableSupportPhone: enableSupportPhone })), activeTab === 'integrations' && (jsx(IntegrationsTab, { tenantKey: tenant, username: username })), activeTab === 'billing' && (jsx(BillingTab, { tenant: tenant, userActiveApp: userActiveApp, username: username, currentUserEmail: email, mainPlatformKey: mainPlatformKey })), activeTab === 'monetization' && (jsx(MonetizationTab, { platformKey: tenant, authURL: authURL })), activeTab === 'advanced' && (jsx(AdvancedTab, { platformKey: tenant, currentSPA: currentSPA, username: username, authURL: authURL, currentPlatformBaseDomain: currentPlatformBaseDomain }))] })] }), jsx(ToastProvider, {})] }));
252233
252234
  }
252234
252235
 
252235
- function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showUsernameField = false, showPlatformName = false, useGravatarPicFallback = true, enableCatalogInvite = false, targetTab = 'basic', currentPlan = '', currentSPA = '', userActiveApp = null, authURL, tenants = [], onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', onBillingTabRequest, onAccountDeleted, enableMemoryTab = false, localLLMProps, systemControlProps, enableSupportPhone, }) {
252236
+ function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showGradebookTab = false, showUsernameField = false, showPlatformName = false, useGravatarPicFallback = true, enableCatalogInvite = false, targetTab = 'basic', currentPlan = '', currentSPA = '', userActiveApp = null, authURL, tenants = [], onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, onTabChange, defaultSupportPhone = '', onBillingTabRequest, onAccountDeleted, enableMemoryTab = false, localLLMProps, systemControlProps, enableSupportPhone, }) {
252236
252237
  const t = useT();
252237
252238
  console.log('[UserProfileModal] localLLMProps received:', {
252238
252239
  isAvailable: localLLMProps === null || localLLMProps === void 0 ? void 0 : localLLMProps.isAvailable,
@@ -252297,7 +252298,8 @@ function UserProfileModal({ isOpen, onClose, params, email, mainPlatformKey, sho
252297
252298
  showUsernameField: showUsernameField,
252298
252299
  showPlatformName: showPlatformName,
252299
252300
  useGravatarPicFallback: useGravatarPicFallback,
252300
- }, isAdmin: params.isAdmin, targetTab: targetTab, onClose: onClose, onAccountDeleted: onAccountDeleted, enableMemoryTab: enableMemoryTab, localLLMProps: localLLMProps, systemControlProps: systemControlProps })), ['organization', 'management', 'integrations', 'billing', 'monetization'].includes(targetTab) && (jsxs(Fragment$1, { children: [jsx(Account, { onInviteClick: () => setIsInviteUserDialogOpen(true), tenant: params.tenantKey, tenants: tenants, username: getUserName$1(), email: email, mainPlatformKey: mainPlatformKey, showUsernameField: showUsernameField, showPlatformName: showPlatformName, useGravatarPicFallback: useGravatarPicFallback, onClose: onClose, isAdmin: params.isAdmin, targetTab: targetTab, currentPlan: currentPlan, currentSPA: currentSPA, userActiveApp: userActiveApp, authURL: authURL, onTenantUpdate: onTenantUpdate, currentPlatformBaseDomain: currentPlatformBaseDomain, rbacPermissions: rbacPermissions, enableRbac: enableRbac, onLoadGroupPermissions: onLoadGroupPermissions, onTabChange: onTabChange, defaultSupportPhone: defaultSupportPhone, enableSupportPhone: enableSupportPhone }), isInviteUserDialogOpen && (jsx(InviteUserDialog, { tenant: params.tenantKey, onClose: () => setIsInviteUserDialogOpen(false), isOpen: isInviteUserDialogOpen, enableCatalogInvite: enableCatalogInvite, hasManageUsersPermission: hasManageUsersPermission })), isInvitedUsersDialogOpen && (jsx(InvitedUsersDialog, { onClose: () => setIsInvitedUsersDialogOpen(false), tenant: params.tenantKey }))] }))] }) }) }));
252301
+ showGradebookTab: showGradebookTab,
252302
+ }, isAdmin: params.isAdmin, targetTab: targetTab, onClose: onClose, onAccountDeleted: onAccountDeleted, enableMemoryTab: enableMemoryTab, localLLMProps: localLLMProps, systemControlProps: systemControlProps })), ['organization', 'management', 'integrations', 'billing', 'monetization'].includes(targetTab) && (jsxs(Fragment$1, { children: [jsx(Account, { onInviteClick: () => setIsInviteUserDialogOpen(true), tenant: params.tenantKey, tenants: tenants, username: getUserName$1(), email: email, mainPlatformKey: mainPlatformKey, showUsernameField: showUsernameField, showPlatformName: showPlatformName, useGravatarPicFallback: useGravatarPicFallback, onClose: onClose, isAdmin: params.isAdmin, targetTab: targetTab, currentPlan: currentPlan, currentSPA: currentSPA, userActiveApp: userActiveApp, authURL: authURL, onTenantUpdate: onTenantUpdate, currentPlatformBaseDomain: currentPlatformBaseDomain, rbacPermissions: rbacPermissions, enableRbac: enableRbac, onLoadGroupPermissions: onLoadGroupPermissions, onTabChange: onTabChange, defaultSupportPhone: defaultSupportPhone, enableSupportPhone: enableSupportPhone, showGradebookTab: showGradebookTab }), isInviteUserDialogOpen && (jsx(InviteUserDialog, { tenant: params.tenantKey, onClose: () => setIsInviteUserDialogOpen(false), isOpen: isInviteUserDialogOpen, enableCatalogInvite: enableCatalogInvite, hasManageUsersPermission: hasManageUsersPermission })), isInvitedUsersDialogOpen && (jsx(InvitedUsersDialog, { onClose: () => setIsInvitedUsersDialogOpen(false), tenant: params.tenantKey }))] }))] }) }) }));
252301
252303
  }
252302
252304
 
252303
252305
  const IS_SERVER = typeof window === 'undefined';
@@ -253048,7 +253050,7 @@ className = '', dropdownClassName = 'mr-4 w-56 bg-white border border-gray-200 s
253048
253050
  // Additional data
253049
253051
  metadata, metadataLoaded = false,
253050
253052
  // Customization
253051
- currentSPA = '', showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showUsernameField = false, showPlatformName = false, enableCatalogInvite = false, authURL, onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, defaultSupportPhone = '', enableSupportPhone,
253053
+ currentSPA = '', showMentorAIDisplayCheckbox = false, showLeaderboardDisplayCheckbox = false, showGradebookTab = false, showUsernameField = false, showPlatformName = false, enableCatalogInvite = false, authURL, onTenantUpdate, currentPlatformBaseDomain = '', rbacPermissions = {}, enableRbac = false, onLoadGroupPermissions, defaultSupportPhone = '', enableSupportPhone,
253052
253054
  // Local LLM props
253053
253055
  localLLMProps,
253054
253056
  // System Control props
@@ -253236,6 +253238,7 @@ isModalOpen, onModalOpenChange, defaultActiveTab, onAccountDeleted, enableMemory
253236
253238
  currentPlan,
253237
253239
  currentSPA,
253238
253240
  showMentorAIDisplayCheckbox,
253241
+ showGradebookTab,
253239
253242
  showLeaderboardDisplayCheckbox,
253240
253243
  showUsernameField,
253241
253244
  showPlatformName,
@@ -261939,6 +261942,20 @@ function toArray(data) {
261939
261942
  }
261940
261943
  return [];
261941
261944
  }
261945
+ /** Page size requested for the paginated LTI list tabs. */
261946
+ const LTI_PAGE_SIZE = 10;
261947
+ /**
261948
+ * Total page count from a paginated LTI list envelope. Reads the backend's
261949
+ * `num_pages`; falls back to a single page when the response isn't paginated.
261950
+ */
261951
+ function getTotalPages(data) {
261952
+ if (data && typeof data === 'object') {
261953
+ const n = data.num_pages;
261954
+ if (typeof n === 'number' && n > 0)
261955
+ return n;
261956
+ }
261957
+ return 1;
261958
+ }
261942
261959
  /**
261943
261960
  * Pull a human-readable message out of an RTK Query / fetch error so we can
261944
261961
  * surface backend-supplied detail (e.g. "key is associated with tool X") to
@@ -262083,12 +262100,14 @@ function AgentLinksSection({ identity, labels, }) {
262083
262100
  const { platformKey, mentorId, mentorUniqueId, username, isLtiAccessible, isReady, isSettingsLoading } = identity;
262084
262101
  const [showCreate, setShowCreate] = React__default.useState(false);
262085
262102
  const [editingLink, setEditingLink] = React__default.useState(null);
262086
- const { data: allLinks, isLoading, isFetching, } = useGetLtiMentorsQuery({ platformKey, mentorId: mentorUniqueId }, { skip: !isReady });
262103
+ const [page, setPage] = React__default.useState(1);
262104
+ const { data: allLinks, isLoading, isFetching, } = useGetLtiMentorsQuery({ platformKey, mentorId: mentorUniqueId, page, pageSize: LTI_PAGE_SIZE }, { skip: !isReady });
262087
262105
  // The backend scopes the list to this agent via `mentor_id`; we still narrow
262088
262106
  // client-side by the unique_id as a defensive safety net.
262089
262107
  const links = React__default.useMemo(() => mentorUniqueId
262090
262108
  ? toArray(allLinks).filter((link) => { var _a; return ((_a = link.mentor_config) === null || _a === void 0 ? void 0 : _a.mentor) === mentorUniqueId; })
262091
262109
  : [], [allLinks, mentorUniqueId]);
262110
+ const totalPages = getTotalPages(allLinks);
262092
262111
  const busy = !isReady || isSettingsLoading || isLoading;
262093
262112
  const canCreate = !busy && links.length === 0 && Boolean(mentorUniqueId);
262094
262113
  return (jsxs("div", { className: "space-y-4", "data-testid": "lti-links-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.links.description }), canCreate && (jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-link-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.links.createButton] }))] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : links.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-links-empty", children: [jsx(Link2, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.links.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.links.targetUriColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: links.map((link) => {
@@ -262097,7 +262116,7 @@ function AgentLinksSection({ identity, labels, }) {
262097
262116
  event.stopPropagation();
262098
262117
  setEditingLink(link);
262099
262118
  }, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, link.id));
262100
- }) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), showCreate && (jsx(AgentLinkModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, labels: labels })), editingLink && (jsx(AgentLinkModal, { isOpen: Boolean(editingLink), onClose: () => setEditingLink(null), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, link: editingLink, labels: labels }))] }));
262119
+ }) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy || isFetching }), showCreate && (jsx(AgentLinkModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, labels: labels })), editingLink && (jsx(AgentLinkModal, { isOpen: Boolean(editingLink), onClose: () => setEditingLink(null), platformKey: platformKey, mentorId: mentorId, mentorUniqueId: mentorUniqueId, username: username, isLtiAccessible: isLtiAccessible, link: editingLink, labels: labels }))] }));
262101
262120
  }
262102
262121
 
262103
262122
  function KeyCreateModal({ isOpen, onClose, platformKey, labels }) {
@@ -262189,10 +262208,12 @@ function KeysSection({ identity, labels }) {
262189
262208
  const [showCreate, setShowCreate] = React__default.useState(false);
262190
262209
  const [selectedKey, setSelectedKey] = React__default.useState(null);
262191
262210
  const [keyToDelete, setKeyToDelete] = React__default.useState(null);
262192
- const { data: keysData, isLoading, isFetching, } = useGetLtiKeysQuery({ platformKey }, { skip: !isReady });
262211
+ const [page, setPage] = React__default.useState(1);
262212
+ const { data: keysData, isLoading, isFetching, } = useGetLtiKeysQuery({ platformKey, page, pageSize: LTI_PAGE_SIZE }, { skip: !isReady });
262193
262213
  const keys = React__default.useMemo(() => toArray(keysData), [keysData]);
262214
+ const totalPages = getTotalPages(keysData);
262194
262215
  const busy = !isReady || isLoading;
262195
- return (jsxs("div", { className: "space-y-4", "data-testid": "lti-keys-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.keys.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-key-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.keys.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : keys.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-keys-empty", children: [jsx(KeyRound, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.keys.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.keys.publicKeyColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: keys.map((key) => (jsxs(TableRow$1, { "data-testid": "lti-key-row", className: "border-b last:border-0 hover:bg-muted/40", children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: key.name }), jsx(TableCell$1, { className: "p-3 font-mono text-xs text-[#646464]", children: truncateMiddle(key.public_key, 40) }), jsx(TableCell$1, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.keys.actionsAria(key.name), children: jsx(EllipsisVertical, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { onClick: () => setSelectedKey(key), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.common.edit] }), jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", onClick: () => setKeyToDelete(key), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.common.delete] })] })] }) })] }, key.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), showCreate && (jsx(KeyCreateModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), selectedKey && (jsx(KeyDetailModal, { isOpen: Boolean(selectedKey), onClose: () => setSelectedKey(null), platformKey: platformKey, ltiKey: selectedKey, labels: labels })), keyToDelete && (jsx(KeyDeleteModal, { isOpen: Boolean(keyToDelete), onClose: () => setKeyToDelete(null), platformKey: platformKey, ltiKey: keyToDelete, labels: labels }))] }));
262216
+ return (jsxs("div", { className: "space-y-4", "data-testid": "lti-keys-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.keys.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-key-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.keys.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : keys.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-keys-empty", children: [jsx(KeyRound, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.keys.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.keys.publicKeyColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: keys.map((key) => (jsxs(TableRow$1, { "data-testid": "lti-key-row", className: "border-b last:border-0 hover:bg-muted/40", children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: key.name }), jsx(TableCell$1, { className: "p-3 font-mono text-xs text-[#646464]", children: truncateMiddle(key.public_key, 40) }), jsx(TableCell$1, { className: "p-3 text-right", children: jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsx(Button$1, { type: "button", variant: "ghost", size: "icon", "aria-label": labels.keys.actionsAria(key.name), children: jsx(EllipsisVertical, { className: "h-4 w-4" }) }) }), jsxs(DropdownMenuContent, { align: "end", children: [jsxs(DropdownMenuItem, { onClick: () => setSelectedKey(key), children: [jsx(Pencil, { className: "mr-2 h-4 w-4" }), labels.common.edit] }), jsxs(DropdownMenuItem, { className: "text-red-600 focus:text-red-700", onClick: () => setKeyToDelete(key), children: [jsx(Trash2, { className: "mr-2 h-4 w-4" }), labels.common.delete] })] })] }) })] }, key.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy || isFetching }), showCreate && (jsx(KeyCreateModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), selectedKey && (jsx(KeyDetailModal, { isOpen: Boolean(selectedKey), onClose: () => setSelectedKey(null), platformKey: platformKey, ltiKey: selectedKey, labels: labels })), keyToDelete && (jsx(KeyDeleteModal, { isOpen: Boolean(keyToDelete), onClose: () => setKeyToDelete(null), platformKey: platformKey, ltiKey: keyToDelete, labels: labels }))] }));
262196
262217
  }
262197
262218
 
262198
262219
  function FieldError({ field, }) {
@@ -262257,7 +262278,11 @@ function ToolModal({ isOpen, onClose, platformKey, tool, labels }) {
262257
262278
  auth_token_url: value.auth_token_url,
262258
262279
  auth_audience: ((_a = value.auth_audience) === null || _a === void 0 ? void 0 : _a.trim()) ? value.auth_audience.trim() : null,
262259
262280
  key_set_url: value.key_set_mode === 'url' ? (_b = value.key_set_url) === null || _b === void 0 ? void 0 : _b.trim() : null,
262260
- key_set: value.key_set_mode === 'raw' ? JSON.parse(value.key_set) : null,
262281
+ // The backend serializer stores key_set as a JSON *string* and
262282
+ // rejects a parsed object with 400 "Not a valid string." — send the
262283
+ // raw textarea value (the field validator already guarantees it
262284
+ // parses as JSON).
262285
+ key_set: value.key_set_mode === 'raw' ? value.key_set.trim() : null,
262261
262286
  tool_key: Number(value.tool_key),
262262
262287
  deployment_ids: parseDeploymentIds(value.deployment_ids),
262263
262288
  platform_key: platformKey,
@@ -262319,13 +262344,15 @@ function ToolsSection({ identity, labels }) {
262319
262344
  const { platformKey, isReady } = identity;
262320
262345
  const [showCreate, setShowCreate] = React__default.useState(false);
262321
262346
  const [editingTool, setEditingTool] = React__default.useState(null);
262322
- const { data: toolsData, isLoading, isFetching, } = useGetLtiToolsQuery({ platformKey }, { skip: !isReady });
262347
+ const [page, setPage] = React__default.useState(1);
262348
+ const { data: toolsData, isLoading, isFetching, } = useGetLtiToolsQuery({ platformKey, page, pageSize: LTI_PAGE_SIZE }, { skip: !isReady });
262323
262349
  const tools = React__default.useMemo(() => toArray(toolsData), [toolsData]);
262350
+ const totalPages = getTotalPages(toolsData);
262324
262351
  const busy = !isReady || isLoading;
262325
262352
  return (jsxs("div", { className: "space-y-4", "data-testid": "lti-tools-section", children: [jsxs("div", { className: "flex flex-col items-start justify-between gap-3 sm:flex-row sm:items-center", children: [jsx("p", { className: "text-xs text-gray-600", children: labels.tools.description }), jsxs(Button$1, { onClick: () => setShowCreate(true), size: "sm", "data-testid": "lti-tool-create-button", className: "cursor-pointer whitespace-nowrap bg-gradient-to-r from-[#2563EB] to-[#93C5FD] text-white hover:opacity-90", children: [jsx(Plus, { className: "h-4 w-4" }), labels.tools.createButton] })] }), busy ? (jsx("div", { className: "flex w-full items-center justify-center py-10", children: jsx(Spinner, {}) })) : !tools || tools.length === 0 ? (jsxs("div", { className: "flex flex-col items-center justify-center gap-3 rounded-md border border-dashed border-gray-200 py-12 text-center", "data-testid": "lti-tools-empty", children: [jsx(Wrench, { className: "h-8 w-8 text-gray-300", "aria-hidden": "true" }), jsx("p", { className: "text-sm text-[#646464]", children: labels.tools.empty })] })) : (jsxs("div", { className: "overflow-hidden rounded-md border", children: [jsx("div", { className: "overflow-x-auto", children: jsxs(Table$1, { className: "min-w-full", children: [jsx(TableHeader$1, { children: jsxs(TableRow$1, { className: "bg-muted/50 border-b", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.common.nameColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.tools.issuerColumn }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: labels.tools.clientIdColumn }), jsx(TableHead, { className: "p-3 text-right text-sm whitespace-nowrap text-[#646464]", children: labels.common.actionsColumn })] }) }), jsx(TableBody, { children: tools.map((tool) => (jsxs(TableRow$1, { "data-testid": "lti-tool-row", className: "cursor-pointer border-b last:border-0 hover:bg-muted/40", onClick: () => setEditingTool(tool), children: [jsx(TableCell$1, { className: "p-3 text-sm font-medium text-gray-900", children: tool.title }), jsx(TableCell$1, { className: "max-w-[260px] truncate p-3 text-sm text-[#646464]", children: tool.issuer }), jsx(TableCell$1, { className: "max-w-[200px] truncate p-3 text-sm text-[#646464]", children: tool.client_id }), jsx(TableCell$1, { className: "p-3 text-right", children: jsx(Button$1, { type: "button", variant: "outline", size: "icon", "aria-label": labels.tools.editAria(tool.title), onClick: (event) => {
262326
262353
  event.stopPropagation();
262327
262354
  setEditingTool(tool);
262328
- }, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, tool.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), showCreate && (jsx(ToolModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), editingTool && (jsx(ToolModal, { isOpen: Boolean(editingTool), onClose: () => setEditingTool(null), platformKey: platformKey, tool: editingTool, labels: labels }))] }));
262355
+ }, children: jsx(Pencil, { className: "h-4 w-4" }) }) })] }, tool.id))) })] }) }), isFetching && (jsx("p", { className: "px-3 py-2 text-xs text-gray-400", children: labels.common.refreshing }))] })), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: busy || isFetching }), showCreate && (jsx(ToolModal, { isOpen: showCreate, onClose: () => setShowCreate(false), platformKey: platformKey, labels: labels })), editingTool && (jsx(ToolModal, { isOpen: Boolean(editingTool), onClose: () => setEditingTool(null), platformKey: platformKey, tool: editingTool, labels: labels }))] }));
262329
262356
  }
262330
262357
 
262331
262358
  function ToolEndpointsSection({ identity, labels, }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/iblai-js",
3
- "version": "1.21.1",
3
+ "version": "1.22.1",
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": {
@@ -66,10 +66,10 @@
66
66
  "axios": "1.13.6",
67
67
  "dotenv": "16.6.1",
68
68
  "winston": "3.19.0",
69
- "@iblai/data-layer": "1.8.9",
69
+ "@iblai/web-containers": "1.12.1",
70
70
  "@iblai/mcp": "1.7.8",
71
- "@iblai/web-containers": "1.11.1",
72
- "@iblai/web-utils": "1.11.9"
71
+ "@iblai/web-utils": "1.11.9",
72
+ "@iblai/data-layer": "1.9.1"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "@radix-ui/react-dialog": "^1.1.7",