feat: add LTI 1.3 Tool Consumer support with database migrations and API endpoints
- Implemented database migrations for lti_external_tools and lti_grade_passback_events tables in both cms-service and lms-service. - Created API handlers for managing LTI tools including listing, creating, updating, and deleting tools. - Added functionality for LTI grade passback with validation and signature verification. - Developed frontend components for LTI tool management and display in course editor. Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -23,6 +23,7 @@ import PeerReviewPlayer from "@/components/blocks/PeerReviewPlayer";
|
||||
import MermaidViewer from "@/components/blocks/MermaidViewer";
|
||||
import ScormPlayer from "@/components/blocks/ScormPlayer";
|
||||
import PluginBlock from "@/components/blocks/PluginBlock";
|
||||
import LtiToolPlayer from "@/components/blocks/LtiToolPlayer";
|
||||
import InteractiveTranscript from "@/components/InteractiveTranscript";
|
||||
import AITutor from "@/components/AITutor";
|
||||
import LessonLockedView from "@/components/LessonLockedView";
|
||||
@@ -542,6 +543,13 @@ export default function LessonPlayerPage({ params }: { params: { id: string, les
|
||||
launchUrl={block.launch_url || block.url || lesson.content_url || ""}
|
||||
/>
|
||||
);
|
||||
case 'lti-tool':
|
||||
return (
|
||||
<LtiToolPlayer
|
||||
title={block.title || 'Herramienta LTI'}
|
||||
launchUrl={block.launch_url || block.url || ''}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return <div className="p-4 bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 rounded-xl text-xs font-bold text-gray-600 dark:text-gray-500 uppercase tracking-widest">Tipo de Bloque Desconocido: {block.type}</div>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { ExternalLink, ShieldCheck } from "lucide-react";
|
||||
|
||||
interface LtiToolPlayerProps {
|
||||
title: string;
|
||||
launchUrl: string;
|
||||
}
|
||||
|
||||
export default function LtiToolPlayer({ title, launchUrl }: LtiToolPlayerProps) {
|
||||
if (!launchUrl || !launchUrl.startsWith("https://")) {
|
||||
return (
|
||||
<div className="rounded-xl border border-red-200 dark:border-red-900/40 bg-red-50 dark:bg-red-900/20 p-4 text-sm text-red-700 dark:text-red-300">
|
||||
La herramienta LTI no tiene una URL segura (HTTPS) válida.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="rounded-2xl border border-black/10 dark:border-white/10 overflow-hidden bg-white dark:bg-black/20">
|
||||
<header className="px-4 py-3 border-b border-black/5 dark:border-white/5 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2 text-sm font-semibold">
|
||||
<ShieldCheck className="w-4 h-4 text-emerald-500" />
|
||||
{title || "Herramienta Externa"}
|
||||
</div>
|
||||
<a
|
||||
href={launchUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs text-black/40 dark:text-white/40 hover:text-black/70 dark:hover:text-white/70 inline-flex items-center gap-1"
|
||||
>
|
||||
<ExternalLink className="w-3 h-3" />
|
||||
Abrir en pestaña nueva
|
||||
</a>
|
||||
</header>
|
||||
<iframe
|
||||
src={launchUrl}
|
||||
title={title || "Herramienta LTI"}
|
||||
className="w-full"
|
||||
style={{ minHeight: "560px", border: "none" }}
|
||||
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
|
||||
loading="lazy"
|
||||
referrerPolicy="strict-origin-when-cross-origin"
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ export interface QuizQuestion {
|
||||
|
||||
export interface Block {
|
||||
id: string;
|
||||
type: 'description' | 'media' | 'quiz' | 'fill-in-the-blanks' | 'matching' | 'ordering' | 'short-answer' | 'code' | 'hotspot' | 'memory-match' | 'document' | 'audio-response' | 'video_marker' | 'peer-review' | 'role-playing' | 'mermaid' | 'code-lab' | 'scorm' | 'plugin';
|
||||
type: 'description' | 'media' | 'quiz' | 'fill-in-the-blanks' | 'matching' | 'ordering' | 'short-answer' | 'code' | 'hotspot' | 'memory-match' | 'document' | 'audio-response' | 'video_marker' | 'peer-review' | 'role-playing' | 'mermaid' | 'code-lab' | 'scorm' | 'plugin' | 'lti-tool';
|
||||
title: string;
|
||||
content?: string;
|
||||
url?: string;
|
||||
|
||||
Reference in New Issue
Block a user