feat: Implement LTI deep linking, live sessions, predictive analytics, and portfolios with associated UI and database migrations.
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
CREATE TABLE lesson_dependencies (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
organization_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
lesson_id UUID NOT NULL REFERENCES lessons(id) ON DELETE CASCADE,
|
||||
prerequisite_lesson_id UUID NOT NULL REFERENCES lessons(id) ON DELETE CASCADE,
|
||||
min_score_percentage DOUBLE PRECISION,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(lesson_id, prerequisite_lesson_id),
|
||||
CHECK (lesson_id != prerequisite_lesson_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_lesson_dependencies_lesson_id ON lesson_dependencies(lesson_id);
|
||||
CREATE INDEX idx_lesson_dependencies_prerequisite_id ON lesson_dependencies(prerequisite_lesson_id);
|
||||
CREATE INDEX idx_lesson_dependencies_org_id ON lesson_dependencies(organization_id);
|
||||
@@ -0,0 +1,13 @@
|
||||
-- Migration: Add LTI Deep Linking support tables
|
||||
|
||||
CREATE TABLE IF NOT EXISTS lti_deep_linking_requests (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
registration_id UUID NOT NULL REFERENCES lti_registrations(id),
|
||||
deployment_id TEXT NOT NULL,
|
||||
return_url TEXT NOT NULL,
|
||||
data TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Index for cleanup
|
||||
CREATE INDEX idx_lti_dl_requests_created_at ON lti_deep_linking_requests(created_at);
|
||||
@@ -0,0 +1,29 @@
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
CREATE TYPE dropout_risk_level AS ENUM ('low', 'medium', 'high', 'critical');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS dropout_risks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
organization_id UUID NOT NULL REFERENCES organizations(id),
|
||||
course_id UUID NOT NULL REFERENCES courses(id),
|
||||
user_id UUID NOT NULL REFERENCES users(id),
|
||||
risk_level dropout_risk_level NOT NULL DEFAULT 'low',
|
||||
score REAL NOT NULL DEFAULT 0.0,
|
||||
reasons JSONB,
|
||||
last_calculated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(course_id, user_id)
|
||||
);
|
||||
|
||||
-- Trigger for updated_at
|
||||
CREATE TRIGGER update_dropout_risks_updated_at
|
||||
BEFORE UPDATE ON dropout_risks
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
@@ -0,0 +1,24 @@
|
||||
CREATE TABLE meetings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
organization_id UUID NOT NULL REFERENCES organizations(id),
|
||||
course_id UUID NOT NULL REFERENCES courses(id),
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
provider TEXT NOT NULL DEFAULT 'jitsi',
|
||||
meeting_id TEXT NOT NULL,
|
||||
start_at TIMESTAMPTZ NOT NULL,
|
||||
duration_minutes INTEGER NOT NULL,
|
||||
join_url TEXT,
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Index for quick lookup of course meetings
|
||||
CREATE INDEX idx_meetings_course ON meetings(course_id);
|
||||
|
||||
-- Trigger for updated_at
|
||||
CREATE TRIGGER update_meetings_updated_at
|
||||
BEFORE UPDATE ON meetings
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
@@ -0,0 +1,41 @@
|
||||
-- Migration: Portfolios & Badges (Adjustments)
|
||||
-- This migration adjusts existing gamification tables to support the new features
|
||||
|
||||
-- 1. Adjust badges table
|
||||
ALTER TABLE badges ADD COLUMN IF NOT EXISTS criteria JSONB NOT NULL DEFAULT '{}';
|
||||
-- Ensure organization_id has a foreign key if it's missing (optional but good)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'badges_organization_id_fkey') THEN
|
||||
ALTER TABLE badges ADD CONSTRAINT badges_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id);
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 2. Adjust user_badges table
|
||||
ALTER TABLE user_badges ADD COLUMN IF NOT EXISTS evidence_url TEXT;
|
||||
-- Rename earned_at to awarded_at if needed, or just use earned_at in code.
|
||||
-- The model currently expects awarded_at. Let's rename if exists.
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='user_badges' AND column_name='earned_at') THEN
|
||||
ALTER TABLE user_badges RENAME COLUMN earned_at TO awarded_at;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 3. Add profile visibility to users
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS is_public_profile BOOLEAN DEFAULT true;
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS linkedin_url TEXT;
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS github_url TEXT;
|
||||
|
||||
-- 4. Seed some extra default badges if not present
|
||||
INSERT INTO badges (organization_id, name, description, icon_url, requirement_type, requirement_value)
|
||||
SELECT id, 'Open Source Contributor', 'Linked a GitHub account to your profile', '/badges/github.svg', 'points', 0
|
||||
FROM organizations
|
||||
WHERE NOT EXISTS (SELECT 1 FROM badges WHERE name = 'Open Source Contributor')
|
||||
LIMIT 1;
|
||||
|
||||
INSERT INTO badges (organization_id, name, description, icon_url, requirement_type, requirement_value)
|
||||
SELECT id, 'Networking Pro', 'Linked a LinkedIn account to your profile', '/badges/linkedin.svg', 'points', 0
|
||||
FROM organizations
|
||||
WHERE NOT EXISTS (SELECT 1 FROM badges WHERE name = 'Networking Pro')
|
||||
LIMIT 1;
|
||||
Reference in New Issue
Block a user