npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mui-toolpad-extended-tuni/courses

v3.2.2

Published

Courses microservice for MUI Toolpad Extended TUNI

Downloads

51

Readme

@mui-toolpad-extended-tuni/courses

Courses microservice extension for MUI Toolpad Extended TUNI. This package provides course management functionality, course routing, course tools, and course-related components.

Installation

npm install @mui-toolpad-extended-tuni/courses @mui-toolpad-extended-tuni/main @mui-toolpad-extended-tuni/core

Important: You must also install @mui-toolpad-extended-tuni/main and @mui-toolpad-extended-tuni/core as they are required peer dependencies.

Required Peer Dependencies

This package requires the following peer dependencies to be installed:

Required Packages

  • @mui-toolpad-extended-tuni/main: ^3.4.0 - MUST be installed separately
  • @mui-toolpad-extended-tuni/core: ^3.2.0 - MUST be installed separately (also required by main)

React & UI Framework

  • react@^19.0.0
  • react-dom@^19.0.0
  • react-router-dom@^7.0.0
  • @mui/material@^7.0.0
  • @mui/icons-material@^7.0.0
  • @mui/x-date-pickers@^7.0.0
  • @emotion/react@^11.0.0
  • @emotion/styled@^11.0.0
  • axios@^1.7.0
  • zustand@^4.5.0

Installation Example

npm install @mui-toolpad-extended-tuni/courses @mui-toolpad-extended-tuni/main @mui-toolpad-extended-tuni/core \
  react react-dom react-router-dom \
  @mui/material @mui/icons-material @mui/x-date-pickers \
  @emotion/react @emotion/styled \
  axios zustand

API Configuration

This package uses configurable API endpoints. Each microservice accepts its own apiEndpoints prop, allowing you to configure endpoints independently for only the services you use.

Default Endpoints

If no apiEndpoints prop is provided, the package uses these default endpoints:

  • get: "api/courses/" - GET list of courses
  • getById: "api/courses/:id" - GET course by ID (use :id placeholder)
  • getByUrl: "api/courses/?encoded_url=:encodedUrl" - GET course by URL (use :encodedUrl placeholder)
  • post: "api/courses/" - POST create new course
  • put: "api/courses/:id/" - PUT update course (use :id placeholder)
  • delete: "api/chat/courses/:id" - DELETE course (use :id placeholder)

Customizing Endpoints

Configure endpoints directly on the CourseMicroservice component:

import { CourseMicroservice } from '@mui-toolpad-extended-tuni/courses';
import type { CoursesApiEndpoints } from '@mui-toolpad-extended-tuni/courses';

const coursesEndpoints: CoursesApiEndpoints = {
  get: "https://api.example.com/v1/courses",
  getById: "https://api.example.com/v1/courses/:id",
  getByUrl: "https://api.example.com/v1/courses?url=:encodedUrl",
  post: "https://api.example.com/v1/courses",
  put: "https://api.example.com/v1/courses/:id",
  delete: "https://api.example.com/v1/courses/:id",
};

<CourseMicroservice apiEndpoints={coursesEndpoints}>
  {/* Your course microservices */}
</CourseMicroservice>

Note: You can use either full URLs (https://api.example.com/courses) or relative paths (api/courses/). Placeholders like :id will be replaced with actual values at runtime.

Partial Configuration: You can configure only the endpoints you need to customize. Unspecified endpoints will use defaults:

<CourseMicroservice apiEndpoints={{
  get: "api/v2/courses",  // Only override GET endpoint
  // Other endpoints use defaults
}}>
  {/* Your course microservices */}
</CourseMicroservice>

Usage

Basic Setup

The courses microservice automatically registers itself when imported:

import { BrowserRouter } from 'react-router-dom';
import { ToolpadProvider, Microservices } from 'mui-toolpad-extended-tuni';
import { CourseMicroservice } from '@mui-toolpad-extended-tuni/courses';

function App() {
  return (
    <BrowserRouter>
      <ToolpadProvider>
        <Microservices>
          <CourseMicroservice />
          {/* Other microservices */}
        </Microservices>
      </ToolpadProvider>
    </BrowserRouter>
  );
}

Using Course Store

import { useCourseStore } from '@mui-toolpad-extended-tuni/courses';

function MyComponent() {
  const { courses, learningCourses, teachingCourses, getCourses } = useCourseStore();
  
  useEffect(() => {
    getCourses();
  }, [getCourses]);
  
  return (
    <div>
      {learningCourses.map(course => (
        <div key={course.id}>{course.title}</div>
      ))}
    </div>
  );
}

Course Components

import { CourseList, CourseItem, CourseTools } from '@mui-toolpad-extended-tuni/courses';

function CoursesPage() {
  return (
    <CourseList displayMode="course" />
  );
}

Course Navigation Builder

import { CourseNavigationBuilder } from '@mui-toolpad-extended-tuni/courses';

function Navigation() {
  return <CourseNavigationBuilder />;
}

Creating Custom Course Microservices

You can create custom microservices that integrate with the course system. Here's a complete example:

import ScienceIcon from "@mui/icons-material/Science";
import { useMemo, useEffect } from "react";
import { NavigationPageStoreItem } from "mui-toolpad-extended-tuni";
import { useCourseMicroserviceRegistration } from '@mui-toolpad-extended-tuni/courses';

/**
 * Example: EduTest Course Microservice
 * 
 * This demonstrates how to create a self-contained tool that integrates
 * with the Course system. Must be rendered as a child of CourseMicroservice.
 */
const EduTest = () => {
  const {
    registerCourseMicroservice,
    unregisterCourseMicroservice,
  } = useCourseMicroserviceRegistration();

  // Define navigation structure with nested routes
  const eduTestNavigation: NavigationPageStoreItem = useMemo(
    () => ({
      kind: "page",
      segment: "edutest",
      title: "EduTest",
      iconFC: ScienceIcon,
      metadata: {
        description: "EduTest is a microservice for testing",
        forRoles: ["teacher", "student"],
        isRootTool: true,
      },
      children: [
        {
          kind: "page",
          segment: "dashboard",
          title: "Dashboard",
          view: DashboardView,
          metadata: {
            description: "Dashboard for EduTest",
            forRoles: ["teacher", "student"],
          },
          children: [
            {
              kind: "page",
              segment: "subdashboard",
              title: "SubDashboard",
              showTitle: false, // Hide title in UI
              view: SubDashboardView,
              metadata: {
                description: "SubDashboard for EduTest",
                forRoles: ["teacher", "student"],
              },
            },
          ],
        },
        {
          kind: "page",
          segment: "assignments",
          title: "Assignments",
          view: AssignmentsView,
          metadata: {
            description: "Assignments for EduTest",
            forRoles: ["teacher", "student"],
          },
        },
      ],
    }),
    []
  );

  useEffect(() => {
    registerCourseMicroservice(eduTestNavigation);
    return () => {
      unregisterCourseMicroservice(eduTestNavigation.segment);
    };
  }, [registerCourseMicroservice, unregisterCourseMicroservice, eduTestNavigation]);

  return null; // This component doesn't render anything
};

// Your view components
const DashboardView = () => <div>Dashboard View</div>;
const AssignmentsView = () => <div>Assignments View</div>;
const SubDashboardView = () => <div>SubDashboard View</div>;

export default EduTest;

Usage in your app:

import { CourseMicroservice } from '@mui-toolpad-extended-tuni/courses';
import EduTest from './EduTest';

function App() {
  return (
    <CourseMicroservice>
      <EduTest />
      {/* Other course microservices */}
    </CourseMicroservice>
  );
}

This creates routes like:

  • /courses/:courseCode/:instance/edutest - Shows tool selector
  • /courses/:courseCode/:instance/edutest/dashboard - Shows Dashboard view
  • /courses/:courseCode/:instance/edutest/dashboard/subdashboard - Shows SubDashboard view
  • /courses/:courseCode/:instance/edutest/assignments - Shows Assignments view

EventBus Integration with Calendar Package

The courses package automatically publishes course events to the EventBus, which the calendar package can consume for automatic calendar integration. This integration is automatic - no additional setup needed!

How It Works

  1. Courses Package includes CourseEventPublisher (automatically included in CourseMicroservice) which:

    • Monitors course data from useCourseStore
    • Converts course events (lectures, exercises, exams, deadlines) to generic calendar events
    • Publishes them to the EventBus via eventBus.publish('courses', events)
  2. Calendar Package includes CalendarEventAggregator (automatically included in CalendarMicroservice) which:

    • Subscribes to EventBus events
    • Converts generic events to calendar events with proper colors
    • Updates the calendar display automatically

Setup for EventBus Integration

Simply include both microservices - the integration happens automatically:

import { BrowserRouter } from 'react-router-dom';
import { ToolpadProvider, Microservices } from 'mui-toolpad-extended-tuni';
import { CourseMicroservice } from '@mui-toolpad-extended-tuni/courses';
import { CalendarMicroservice } from '@mui-toolpad-extended-tuni/calendar';

function App() {
  return (
    <BrowserRouter>
      <ToolpadProvider>
        <Microservices>
          {/* CourseEventPublisher is automatically included */}
          <CourseMicroservice />
          
          {/* CalendarEventAggregator is automatically included */}
          <CalendarMicroservice />
        </Microservices>
      </ToolpadProvider>
    </BrowserRouter>
  );
}

That's it! When both packages are installed:

  • ✅ Course events (lectures, exercises, exams, deadlines) are automatically published to the EventBus
  • ✅ The calendar automatically receives and displays these events
  • ✅ Events are color-coded by course subject and level
  • ✅ No additional configuration needed - it works automatically!

Event Structure

Course events are published with this structure:

{
  id: string;
  title: string;
  start: string; // ISO date string
  end: string; // ISO date string
  metadata: {
    source: 'courses',
    courseCode: string;
    courseTitle: string;
    subject: string;
    courseLevel: 'basic' | 'intermediate' | 'advanced';
    type: 'lecture' | 'exercise' | 'exam' | 'deadline' | 'other';
    description?: string;
    location?: string;
  }
}

API Endpoints

This package makes the following API calls. All endpoints are configurable via apiConfig.

GET /api/courses/ (or configured get endpoint)

Retrieves a list of all courses.

Request: No body required

Response: 200 OK

[
  {
    "id": "course-123",
    "title": "Introduction to Computer Science",
    "description": "Basic CS concepts",
    "code": "COMP.CS.100",
    "instance": "compcs100-fall-2024",
    "start_date": "2024-09-01T00:00:00Z",
    "end_date": "2024-12-15T23:59:59Z",
    "created_at": "2024-08-01T10:00:00Z",
    "updated_at": "2024-08-15T14:30:00Z",
    "visibility": {
      "mode": "public",
      "start_date": null,
      "end_date": null
    },
    "events": {
      "lecture": [],
      "exercise": [],
      "exam": [],
      "deadline": [],
      "other": []
    },
    "data_processing": {
      "purposes": ["course_delivery", "assessment"],
      "retention": 365,
      "third_party_processors": [],
      "special_categories": false,
      "legal_basis": "consent"
    }
  }
]

Response Type: Course[] (array of Course objects)

GET /api/courses/:id (or configured getById endpoint)

Retrieves a single course by ID.

Request Parameters:

  • :id (path parameter) - Course ID

Response: 200 OK

{
  "id": "course-123",
  "title": "Introduction to Computer Science",
  "description": "Basic CS concepts",
  "code": "COMP.CS.100",
  "instance": "compcs100-fall-2024",
  // ... same structure as list endpoint
}

Response Type: Course

GET /api/courses/?encoded_url=:encodedUrl (or configured getByUrl endpoint)

Retrieves a course by URL (base64-encoded).

Request Parameters:

  • encoded_url (query parameter) - Base64-encoded course URL

Response: 200 OK (array with single course)

[
  {
    "id": "course-123",
    // ... course object
  }
]

Response Type: Course[] (array with one Course)

POST /api/courses/ (or configured post endpoint)

Creates a new course.

Request Body: CourseRaw (snake_case)

{
  "title": "Introduction to Computer Science",
  "description": "Basic CS concepts",
  "code": "COMP.CS.100",
  "instance": "compcs100-fall-2024",
  "start_date": "2024-09-01T00:00:00Z",
  "end_date": "2024-12-15T23:59:59Z",
  "visibility": {
    "mode": "public",
    "start_date": null,
    "end_date": null
  },
  "events": {
    "lecture": [],
    "exercise": [],
    "exam": [],
    "deadline": [],
    "other": []
  },
  "data_processing": {
    "purposes": ["course_delivery", "assessment"],
    "retention": 365,
    "third_party_processors": [],
    "special_categories": false,
    "legal_basis": "consent"
  }
}

Response: 201 Created

{
  "id": "course-123",
  "title": "Introduction to Computer Science",
  // ... full Course object with generated ID and timestamps
  "created_at": "2024-08-01T10:00:00Z",
  "updated_at": "2024-08-01T10:00:00Z"
}

Response Type: Course

Note: The request body should be in snake_case format. The package automatically converts from camelCase.

PUT /api/courses/:id/ (or configured put endpoint)

Updates an existing course.

Request Parameters:

  • :id (path parameter) - Course ID

Request Body: Course (snake_case, must include id)

{
  "id": "course-123",
  "title": "Updated Course Title",
  "description": "Updated description",
  // ... all Course fields
}

Response: 200 OK

{
  "id": "course-123",
  "title": "Updated Course Title",
  // ... updated Course object
  "updated_at": "2024-08-15T14:30:00Z"
}

Response Type: Course

DELETE /api/chat/courses/:id (or configured delete endpoint)

Deletes a course.

Request Parameters:

  • :id (path parameter) - Course ID

Response: 200 OK

{
  "id": "course-123",
  // ... deleted Course object
}

Response Type: Course

Data Types

Course

Complete course object returned by API (includes id, createdAt, updatedAt).

interface Course extends CourseRaw {
  id: string;                    // Unique course ID
  createdAt: string;             // ISO date string - when course was created
  updatedAt: string;             // ISO date string - when course was last updated
}

CourseRaw

Course data for creating/updating courses (request body format).

interface CourseRaw {
  title: string;                  // Course title (required)
  description: string;            // Course description (required)
  code: string;                  // Course code, e.g., "COMP.CS.300" (required)
  instance: string;               // Instance identifier, e.g., "compcs300-october-2024" (required)
  ltiLoginUrl?: string;           // LTI login URL (optional)
  services?: string[];            // List of services used (optional)
  image?: {                       // Course images (optional)
    large: string;                // 1200x800px image URL
    medium: string;               // 600x400px image URL
    thumbnail: string;            // 300x200px image URL
  };
  startDate: string | null;       // ISO date string - course start date
  endDate: string | null;         // ISO date string - course end date
  visibility: {                   // Visibility settings
    mode: "public" | "enrolled" | "private";
    startDate: string | null;     // When course becomes visible
    endDate: string | null;       // When visibility ends
  };
  events: {                        // Course events by type
    lecture: CourseEvent[];
    exercise: CourseEvent[];
    exam: CourseEvent[];
    deadline: CourseEvent[];
    other: CourseEvent[];
  };
  tags?: string[];                 // Course tags for categorization
  language?: string;              // ISO 639-1 language code
  dataProcessing: {                // GDPR data processing info
    purposes: string[];            // What data is used for
    retention: number;             // Retention period in days
    thirdPartyProcessors: Array<{
      name: string;
      purpose: string;
      dataShared: string[];
    }>;
    specialCategories: boolean;   // Special categories of personal data
    legalBasis: "consent" | "contract" | "legal_obligation" | "legitimate_interests";
  };
  enrollment?: {                    // Enrollment settings
    startDate: string | null;      // Enrollment opens
    endDate: string | null;        // Enrollment closes
    status: {
      open: boolean;              // Whether new enrollments accepted
      maxStudents?: number;       // Maximum students (optional)
    };
  };
  relationships?: {                 // Course relationships
    prerequisites: CourseRelation[];
    continuations: CourseRelation[];
    alternatives: CourseRelation[];
    related: CourseRelation[];
  };
  studyModule?: {                   // Study module info
    name: string;                  // Module name
    order?: number;                 // Order within module
    credits: number;                // Credit points
    level: "basic" | "intermediate" | "advanced";
  };
}

CourseEvent

Individual course event (lecture, exercise, exam, etc.).

interface CourseEvent {
  id: string;                      // Event ID
  type: "lecture" | "exercise" | "exam" | "deadline" | "other";
  title: string;                   // Event title
  description?: string;             // Event description
  startTime: string;                // ISO date string - event start
  endTime?: string;                 // ISO date string - event end
  location?: string;                // Physical or virtual location
  teachers?: EnrollmentData[];      // Array of teachers
  recurring?: {                      // Recurring event settings
    frequency: "daily" | "weekly" | "biweekly";
    until: string;                  // ISO date string - when recurrence ends
    exceptions?: string[];           // ISO date strings - cancelled dates
  };
  maxParticipants?: number;          // Maximum participants
  requiresRegistration?: boolean;   // Whether registration required
}

EnrollmentData

User enrollment information for a course.

interface EnrollmentData {
  courseId: string;                 // Course ID
  userId: string;                   // User ID
  name: string;                     // User name
  email: string;                    // User email
  role: "student" | "teacher" | "guest";
  status: "enrolled" | "pending" | "rejected";
}

CourseRelation

Relationship between courses (prerequisites, continuations, etc.).

interface CourseRelation {
  code: string;                     // Related course code
  type: "prerequisite" | "recommended" | "parallel" | "continues_from" | 
        "alternative_to" | "part_of" | "prepares_for";
  description?: string;              // Why courses are related
  required?: boolean;                // Hard requirement or suggestion
}

Type Definitions

type courseRole = "student" | "teacher" | "guest";
type visibilityMode = "public" | "enrolled" | "private";
type courseEventType = "lecture" | "exercise" | "exam" | "deadline" | "other";
type courseEventFrequency = "daily" | "weekly" | "biweekly";
type legalBasis = "consent" | "contract" | "legal_obligation" | "legitimate_interests";
type enrollmentStatus = "enrolled" | "pending" | "rejected";
type courseLevel = "basic" | "intermediate" | "advanced";
type courseRelationType = "prerequisite" | "recommended" | "parallel" | 
                          "continues_from" | "alternative_to" | "part_of" | "prepares_for";

Exports

Components

  • CourseMicroservice - Main microservice component
  • CourseList - List of courses
  • CourseItem - Individual course item
  • CourseTools - Course tools displayer
  • CourseNavigationBuilder - Navigation builder for courses
  • CourseCodeLoader - Loader for course code routes
  • CourseInstanceLoader - Loader for course instance routes
  • CourseInstanceSelector - Selector for course instances
  • LtiLoginUrlForm - LTI login URL form

Hooks

  • useCourseMicroserviceRegistration - Hook for registering custom course microservices (must be used within CourseMicroservice context)
  • useCoursesApiConfig - Hook to access courses API endpoint configuration

Store

  • useCourseStore - Zustand store for course management

Network Functions

  • getCourses() - Fetch all courses
  • getCourseById(courseId: string) - Fetch course by ID
  • getCourseByUrl(url: string) - Fetch course by URL
  • addCourse(courseData: CourseRaw) - Create new course
  • updateCourse(course: Course) - Update existing course
  • deleteCourse(courseId: string) - Delete course

Types

  • Course - Complete course object (with id, timestamps)
  • CourseRaw - Course data for create/update requests
  • CourseEvent - Individual course event
  • EnrollmentData - User enrollment information
  • CourseRelation - Course relationship
  • CoursesApiEndpoints - API endpoint configuration type
  • courseRole - Course role type
  • courseLevel - Course level type
  • courseEventType - Course event type
  • enrollmentStatus - Enrollment status type
  • visibilityMode - Visibility mode type
  • courseEventFrequency - Event frequency type
  • legalBasis - Legal basis for data processing
  • courseRelationType - Course relation type

Features

  • Course management and CRUD operations
  • Course enrollment handling
  • Course navigation integration
  • Course tools and microservices
  • Course filtering and grouping
  • Course instance support
  • LTI integration support

License

MIT