@memberjunction/actions-bizapps-lms
Version:
LMS system integration actions for MemberJunction
437 lines • 17.8 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetLearnWorldsCoursesAction = void 0;
const global_1 = require("@memberjunction/global");
const learnworlds_base_action_1 = require("../learnworlds-base.action");
const actions_1 = require("@memberjunction/actions");
/**
* Action to retrieve courses from LearnWorlds LMS
*/
let GetLearnWorldsCoursesAction = class GetLearnWorldsCoursesAction extends learnworlds_base_action_1.LearnWorldsBaseAction {
/**
* Description of the action
*/
get Description() {
return 'Retrieves the course catalog from LearnWorlds with filtering, search, and sorting options';
}
/**
* Main execution method
*/
async InternalRunAction(params) {
try {
const contextUser = params.ContextUser;
if (!contextUser) {
return {
Success: false,
ResultCode: 'ERROR',
Message: 'Context user is required for LearnWorlds API calls'
};
}
// Store params for base class methods
this.params = params.Params;
// Build query parameters
const queryParams = {};
// Search filter
const searchText = this.getParamValue(params.Params, 'SearchText');
if (searchText) {
queryParams.search = searchText;
}
// Status filter
const status = this.getParamValue(params.Params, 'Status');
if (status) {
queryParams.status = status;
}
// Category filter
const categoryId = this.getParamValue(params.Params, 'CategoryID');
if (categoryId) {
queryParams.category_id = categoryId;
}
// Level filter
const level = this.getParamValue(params.Params, 'Level');
if (level) {
queryParams.level = level;
}
// Language filter
const language = this.getParamValue(params.Params, 'Language');
if (language) {
queryParams.language = language;
}
// Price filters
const onlyFree = this.getParamValue(params.Params, 'OnlyFree');
if (onlyFree) {
queryParams.is_free = true;
}
const minPrice = this.getParamValue(params.Params, 'MinPrice');
if (minPrice !== null && minPrice !== undefined) {
queryParams.min_price = minPrice;
}
const maxPrice = this.getParamValue(params.Params, 'MaxPrice');
if (maxPrice !== null && maxPrice !== undefined) {
queryParams.max_price = maxPrice;
}
// Tags filter
const tags = this.getParamValue(params.Params, 'Tags');
if (tags) {
queryParams.tags = tags;
}
// Instructor filter
const instructorId = this.getParamValue(params.Params, 'InstructorID');
if (instructorId) {
queryParams.instructor_id = instructorId;
}
// Date filters
const createdAfter = this.getParamValue(params.Params, 'CreatedAfter');
if (createdAfter) {
queryParams.created_after = this.formatLearnWorldsDate(new Date(createdAfter));
}
const createdBefore = this.getParamValue(params.Params, 'CreatedBefore');
if (createdBefore) {
queryParams.created_before = this.formatLearnWorldsDate(new Date(createdBefore));
}
// Sorting
const sortBy = this.getParamValue(params.Params, 'SortBy') || 'created';
const sortOrder = this.getParamValue(params.Params, 'SortOrder') || 'desc';
queryParams.sort = `${sortOrder === 'asc' ? '' : '-'}${sortBy}`;
// Include extra data
const includeEnrollmentStats = this.getParamValue(params.Params, 'IncludeEnrollmentStats') ?? true;
if (includeEnrollmentStats) {
queryParams.include = 'enrollment_stats';
}
// Limit for pagination
const maxResults = this.getParamValue(params.Params, 'MaxResults') || 100;
queryParams.limit = Math.min(maxResults, 100);
// Make the API request
const courses = await this.makeLearnWorldsPaginatedRequest('courses', queryParams, contextUser);
// Map to our interface
const mappedCourses = courses.map(course => this.mapLearnWorldsCourse(course));
// Calculate summary
const summary = this.calculateCourseCatalogSummary(mappedCourses);
// Create output parameters
if (!params.Params.find(p => p.Name === 'Courses')) {
params.Params.push({
Name: 'Courses',
Type: 'Output',
Value: mappedCourses
});
}
else {
params.Params.find(p => p.Name === 'Courses').Value = mappedCourses;
}
if (!params.Params.find(p => p.Name === 'TotalCount')) {
params.Params.push({
Name: 'TotalCount',
Type: 'Output',
Value: mappedCourses.length
});
}
else {
params.Params.find(p => p.Name === 'TotalCount').Value = mappedCourses.length;
}
if (!params.Params.find(p => p.Name === 'Summary')) {
params.Params.push({
Name: 'Summary',
Type: 'Output',
Value: summary
});
}
else {
params.Params.find(p => p.Name === 'Summary').Value = summary;
}
return {
Success: true,
ResultCode: 'SUCCESS',
Message: `Successfully retrieved ${mappedCourses.length} courses from LearnWorlds`
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
return {
Success: false,
ResultCode: 'ERROR',
Message: errorMessage
};
}
}
/**
* Map LearnWorlds course data to our interface
*/
mapLearnWorldsCourse(lwCourse) {
return {
id: lwCourse.id || lwCourse._id,
title: lwCourse.title,
subtitle: lwCourse.subtitle,
description: lwCourse.description,
shortDescription: lwCourse.short_description || lwCourse.excerpt,
status: this.mapCourseStatus(lwCourse.status),
visibility: this.mapCourseVisibility(lwCourse.visibility || lwCourse.access_type),
isActive: lwCourse.is_active !== false,
isFree: lwCourse.is_free || lwCourse.price === 0,
price: lwCourse.price,
currency: lwCourse.currency || 'USD',
originalPrice: lwCourse.original_price,
discountPercentage: this.calculateDiscountPercentage(lwCourse.original_price, lwCourse.price),
categoryId: lwCourse.category_id || lwCourse.category?.id,
categoryName: lwCourse.category_name || lwCourse.category?.name,
tags: lwCourse.tags || [],
level: this.mapCourseLevel(lwCourse.level || lwCourse.difficulty),
language: lwCourse.language || 'en',
duration: lwCourse.duration || lwCourse.estimated_duration,
thumbnailUrl: lwCourse.thumbnail_url || lwCourse.image,
coverImageUrl: lwCourse.cover_image_url || lwCourse.cover_image,
promoVideoUrl: lwCourse.promo_video_url || lwCourse.video_url,
instructorId: lwCourse.instructor_id || lwCourse.instructor?.id || lwCourse.author_id,
instructorName: lwCourse.instructor_name || lwCourse.instructor?.name || lwCourse.author_name,
instructorBio: lwCourse.instructor_bio || lwCourse.instructor?.bio,
instructorAvatarUrl: lwCourse.instructor_avatar || lwCourse.instructor?.avatar_url,
totalUnits: lwCourse.total_units || lwCourse.sections_count || 0,
totalLessons: lwCourse.total_lessons || lwCourse.lessons_count || 0,
totalQuizzes: lwCourse.total_quizzes || lwCourse.quizzes_count || 0,
totalAssignments: lwCourse.total_assignments || lwCourse.assignments_count || 0,
estimatedDuration: lwCourse.estimated_duration || lwCourse.total_duration,
totalEnrollments: lwCourse.total_enrollments || lwCourse.students_count || 0,
activeEnrollments: lwCourse.active_enrollments || lwCourse.active_students || 0,
completionRate: lwCourse.completion_rate || 0,
averageRating: lwCourse.average_rating || lwCourse.rating,
totalReviews: lwCourse.total_reviews || lwCourse.reviews_count,
createdAt: this.parseLearnWorldsDate(lwCourse.created || lwCourse.created_at),
updatedAt: this.parseLearnWorldsDate(lwCourse.updated || lwCourse.updated_at),
publishedAt: lwCourse.published_at ? this.parseLearnWorldsDate(lwCourse.published_at) : undefined,
enrollmentStartDate: lwCourse.enrollment_start ? this.parseLearnWorldsDate(lwCourse.enrollment_start) : undefined,
enrollmentEndDate: lwCourse.enrollment_end ? this.parseLearnWorldsDate(lwCourse.enrollment_end) : undefined,
requiresApproval: lwCourse.requires_approval || false,
hasPrerequisites: lwCourse.has_prerequisites || false,
prerequisites: lwCourse.prerequisites || [],
certificateAvailable: lwCourse.certificate_available || lwCourse.has_certificate || false,
objectives: lwCourse.objectives || lwCourse.learning_objectives || [],
targetAudience: lwCourse.target_audience || [],
requirements: lwCourse.requirements || lwCourse.prerequisites_text || []
};
}
/**
* Map course status
*/
mapCourseStatus(status) {
const statusMap = {
'published': 'published',
'active': 'published',
'draft': 'draft',
'unpublished': 'draft',
'coming_soon': 'coming_soon',
'upcoming': 'coming_soon'
};
return statusMap[status?.toLowerCase()] || 'draft';
}
/**
* Map course visibility
*/
mapCourseVisibility(visibility) {
const visibilityMap = {
'public': 'public',
'open': 'public',
'private': 'private',
'closed': 'private',
'hidden': 'hidden',
'unlisted': 'hidden'
};
return visibilityMap[visibility?.toLowerCase()] || 'public';
}
/**
* Map course level
*/
mapCourseLevel(level) {
const levelMap = {
'beginner': 'beginner',
'basic': 'beginner',
'introductory': 'beginner',
'intermediate': 'intermediate',
'medium': 'intermediate',
'advanced': 'advanced',
'expert': 'advanced',
'all': 'all',
'any': 'all',
'mixed': 'all'
};
return levelMap[level?.toLowerCase()] || 'all';
}
/**
* Calculate discount percentage
*/
calculateDiscountPercentage(originalPrice, currentPrice) {
if (!originalPrice || !currentPrice || originalPrice <= currentPrice) {
return undefined;
}
return Math.round(((originalPrice - currentPrice) / originalPrice) * 100);
}
/**
* Calculate course catalog summary
*/
calculateCourseCatalogSummary(courses) {
const summary = {
totalCourses: courses.length,
publishedCourses: courses.filter(c => c.status === 'published').length,
draftCourses: courses.filter(c => c.status === 'draft').length,
freeCourses: courses.filter(c => c.isFree).length,
paidCourses: courses.filter(c => !c.isFree).length,
categoryCounts: {},
levelCounts: {},
languageCounts: {},
enrollmentStats: {
totalEnrollments: 0,
averageEnrollmentsPerCourse: 0,
mostPopularCourses: []
},
priceStats: {
averagePrice: 0,
minPrice: 0,
maxPrice: 0,
currency: 'USD'
}
};
// Count by category
courses.forEach(course => {
if (course.categoryName) {
summary.categoryCounts[course.categoryName] =
(summary.categoryCounts[course.categoryName] || 0) + 1;
}
// Count by level
if (course.level) {
summary.levelCounts[course.level] =
(summary.levelCounts[course.level] || 0) + 1;
}
// Count by language
if (course.language) {
summary.languageCounts[course.language] =
(summary.languageCounts[course.language] || 0) + 1;
}
// Accumulate enrollment stats
summary.enrollmentStats.totalEnrollments += course.totalEnrollments;
});
// Calculate averages
if (courses.length > 0) {
summary.enrollmentStats.averageEnrollmentsPerCourse =
Math.round(summary.enrollmentStats.totalEnrollments / courses.length);
}
// Find most popular courses
summary.enrollmentStats.mostPopularCourses = courses
.filter(c => c.totalEnrollments > 0)
.sort((a, b) => b.totalEnrollments - a.totalEnrollments)
.slice(0, 5)
.map(c => ({
id: c.id,
title: c.title,
enrollments: c.totalEnrollments
}));
// Calculate price statistics for paid courses
const paidCourses = courses.filter(c => !c.isFree && c.price !== undefined);
if (paidCourses.length > 0) {
const prices = paidCourses.map(c => c.price);
summary.priceStats = {
averagePrice: Math.round(prices.reduce((sum, p) => sum + p, 0) / prices.length),
minPrice: Math.min(...prices),
maxPrice: Math.max(...prices),
currency: paidCourses[0].currency || 'USD'
};
}
return summary;
}
/**
* Define the parameters for this action
*/
get Params() {
const baseParams = this.getCommonLMSParams();
const specificParams = [
{
Name: 'SearchText',
Type: 'Input',
Value: null
},
{
Name: 'Status',
Type: 'Input',
Value: null
},
{
Name: 'CategoryID',
Type: 'Input',
Value: null
},
{
Name: 'Level',
Type: 'Input',
Value: null
},
{
Name: 'Language',
Type: 'Input',
Value: null
},
{
Name: 'OnlyFree',
Type: 'Input',
Value: false
},
{
Name: 'MinPrice',
Type: 'Input',
Value: null
},
{
Name: 'MaxPrice',
Type: 'Input',
Value: null
},
{
Name: 'Tags',
Type: 'Input',
Value: null
},
{
Name: 'InstructorID',
Type: 'Input',
Value: null
},
{
Name: 'CreatedAfter',
Type: 'Input',
Value: null
},
{
Name: 'CreatedBefore',
Type: 'Input',
Value: null
},
{
Name: 'SortBy',
Type: 'Input',
Value: 'created'
},
{
Name: 'SortOrder',
Type: 'Input',
Value: 'desc'
},
{
Name: 'IncludeEnrollmentStats',
Type: 'Input',
Value: true
},
{
Name: 'MaxResults',
Type: 'Input',
Value: 100
}
];
return [...baseParams, ...specificParams];
}
};
exports.GetLearnWorldsCoursesAction = GetLearnWorldsCoursesAction;
exports.GetLearnWorldsCoursesAction = GetLearnWorldsCoursesAction = __decorate([
(0, global_1.RegisterClass)(actions_1.BaseAction, 'GetLearnWorldsCoursesAction')
], GetLearnWorldsCoursesAction);
//# sourceMappingURL=get-courses.action.js.map