Files
edu/js/bridges/learning-modal-bridge.js
T

187 lines
6.4 KiB
JavaScript

(function () {
const learningBridgeState = {
initialized: false,
config: null,
markerManager: null,
modal: null,
};
function getLearningConfig() {
if (typeof LEARNING_CONFIG !== 'undefined') {
return LEARNING_CONFIG;
}
if (typeof window.LEARNING_CONFIG !== 'undefined') {
return window.LEARNING_CONFIG;
}
return null;
}
function getMarkerManagerClass() {
if (typeof MarkerManager !== 'undefined') {
return MarkerManager;
}
if (typeof window.MarkerManager !== 'undefined') {
return window.MarkerManager;
}
return null;
}
function getVideoModalClass() {
if (typeof VideoModal !== 'undefined') {
return VideoModal;
}
if (typeof window.VideoModal !== 'undefined') {
return window.VideoModal;
}
return null;
}
function ensureDependencies() {
if (!getLearningConfig()) {
throw new Error('LEARNING_CONFIG is not loaded');
}
if (!getMarkerManagerClass()) {
throw new Error('MarkerManager is not loaded');
}
if (!getVideoModalClass()) {
throw new Error('VideoModal is not loaded');
}
}
function ensureHiddenLearningBridgeContainer() {
let markersContainer = document.getElementById('markers-container');
if (!markersContainer) {
markersContainer = document.createElement('div');
markersContainer.id = 'markers-container';
markersContainer.style.display = 'none';
document.body.appendChild(markersContainer);
}
return markersContainer;
}
function createLearningGaugeStub() {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('id', 'gauge-svg-search-result-bridge');
return {
gaugeSvg: svg,
isMobile: false,
};
}
function buildLearningBridgeChapters(apiChapters) {
const learningConfig = getLearningConfig();
const templateChapters = Array.isArray(learningConfig?.chapters)
? learningConfig.chapters
: [];
const templateByCode = new Map();
templateChapters.forEach(function (chapter, index) {
const code = String(chapter?.code || `__index_${index}`);
templateByCode.set(code, chapter || {});
});
return (Array.isArray(apiChapters) ? apiChapters : []).map(function (apiChapter, chapterIndex) {
const templateChapter = templateByCode.get(String(apiChapter?.code || '')) || templateChapters[chapterIndex] || {};
const templateLessons = Array.isArray(templateChapter.lessons) ? templateChapter.lessons : [];
const lessons = (Array.isArray(apiChapter?.lessons) ? apiChapter.lessons : []).map(function (apiLesson, lessonIndex) {
const templateLesson = templateLessons[lessonIndex] || {};
const label = String(
apiLesson?.title ||
templateLesson.label ||
`${apiChapter?.name || templateChapter.name || '법정교육'} ${lessonIndex + 1}`
);
return {
...templateLesson,
type: 'normal',
label: label,
title: label,
url: String(apiLesson?.url || templateLesson.url || ''),
content_id: String(apiLesson?.content_id || ''),
watch_tm: Number(apiLesson?.watch_tm || 0),
content_tm: Number(apiLesson?.content_tm || 0),
all_tm: Number(apiLesson?.all_tm || 0),
description: String(apiLesson?.description || templateLesson.description || ''),
completed: !!apiLesson?.completed,
};
});
return {
...templateChapter,
id: Number(templateChapter.id || (chapterIndex + 1)),
code: String(apiChapter?.code || templateChapter.code || ''),
name: String(apiChapter?.name || templateChapter.name || `챕터 ${chapterIndex + 1}`),
type: 'chapter',
url: String(lessons[0]?.url || templateChapter.url || ''),
completed: lessons.length > 0 && lessons.every(function (lesson) { return lesson.completed === true; }),
lessons: lessons,
};
});
}
async function hydrateLearningBridge() {
ensureDependencies();
const learningConfig = getLearningConfig();
const MarkerManagerClass = getMarkerManagerClass();
const VideoModalClass = getVideoModalClass();
const response = await fetch('/bbs/api/get_learning_chapters.php', {
credentials: 'same-origin',
});
const payload = await response.json();
if (!response.ok || !payload || payload.success !== true || !Array.isArray(payload.chapters)) {
throw new Error(payload?.message || 'failed_to_load_learning_chapters');
}
const bridgeChapters = buildLearningBridgeChapters(payload.chapters);
const bridgeConfig = {
...learningConfig,
chapters: bridgeChapters,
settings: {
...(learningConfig.settings || {}),
},
};
if (!learningBridgeState.initialized) {
ensureHiddenLearningBridgeContainer();
learningBridgeState.config = bridgeConfig;
learningBridgeState.markerManager = new MarkerManagerClass(createLearningGaugeStub(), bridgeConfig);
learningBridgeState.modal = new VideoModalClass(bridgeConfig, learningBridgeState.markerManager);
if (typeof learningBridgeState.markerManager.setModalInstance === 'function') {
learningBridgeState.markerManager.setModalInstance(learningBridgeState.modal);
}
learningBridgeState.initialized = true;
} else {
learningBridgeState.config = bridgeConfig;
learningBridgeState.markerManager.config = bridgeConfig;
learningBridgeState.markerManager.allMarkers = bridgeConfig.getAllMarkers();
learningBridgeState.modal.config = bridgeConfig;
learningBridgeState.modal.markerManager = learningBridgeState.markerManager;
}
return learningBridgeState;
}
window._learningOpenModal = async function (info) {
const bridge = await hydrateLearningBridge();
const contentId = String(info?.contentId || '');
const allMarkers = typeof bridge.config?.getAllMarkers === 'function'
? bridge.config.getAllMarkers()
: bridge.markerManager.allMarkers;
const globalIndex = allMarkers.findIndex(function (marker) {
return marker && marker.isChapterMarker !== true && String(marker.content_id || '') === contentId;
});
if (globalIndex < 0) {
throw new Error(`learning lesson not found: ${contentId}`);
}
bridge.markerManager.allMarkers = allMarkers;
const lessonData = allMarkers[globalIndex];
await bridge.modal.load(lessonData, globalIndex);
};
})();