feat(platform): ship AI fallback stack and entity-scoped course planning

Unifies the new LangGraph-driven course-plan/media flow with robust provider fallbacks, admin AI provider settings, editable book-style materials, and strict entity isolation across LMS/course-plan APIs. Adds admin-only entity membership management in the Entities UI so users can switch linked entities directly from the platform.

Made-with: Cursor
This commit is contained in:
Yamen Ahmad
2026-04-26 02:34:52 +04:00
parent c2a07a6e5c
commit b4b5868223
23 changed files with 2502 additions and 199 deletions

View File

@@ -2,6 +2,14 @@ import { api } from "@/lib/api-client";
import { asPaginated, asRecordData } from "@/lib/odoo-api";
import type { Entity, EntityRole, PaginatedResponse, PaginationParams, ApiSuccessResponse } from "@/types";
export interface EntityUser {
id: number;
name: string;
login: string;
email: string;
active: boolean;
}
export const entitiesService = {
async list(params?: PaginationParams): Promise<PaginatedResponse<Entity>> {
const raw = await api.get<unknown>("/entities", params as Record<string, string | number | boolean | undefined>);
@@ -42,4 +50,20 @@ export const entitiesService = {
async getPermissions(entityId: number): Promise<string[]> {
return api.get<string[]>(`/permissions`, { entity_id: entityId });
},
async listEntityUsers(entityId: number): Promise<EntityUser[]> {
const raw = await api.get<unknown>(`/entities/${entityId}/users`);
const out = asPaginated<EntityUser>(raw);
return out.items;
},
async updateEntityUsers(entityId: number, userIds: number[]): Promise<ApiSuccessResponse> {
return api.patch<ApiSuccessResponse>(`/entities/${entityId}/users`, { user_ids: userIds });
},
async listPlatformUsers(params?: PaginationParams): Promise<EntityUser[]> {
const raw = await api.get<unknown>("/users/list", params as Record<string, string | number | boolean | undefined>);
const out = asPaginated<EntityUser>(raw);
return out.items;
},
};