@patch-adams/core 1.4.10 → 1.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +177 -17
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +177 -17
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +177 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +177 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2890,7 +2890,8 @@ function generateLrsBridgeCode(options) {
|
|
|
2890
2890
|
sendStatement(statement);
|
|
2891
2891
|
};
|
|
2892
2892
|
|
|
2893
|
-
// Content/Page viewed - uses
|
|
2893
|
+
// Content/Page viewed - uses page-specific object for human-readable display
|
|
2894
|
+
// Object shows page/lesson title, parent context maintains document aggregation
|
|
2894
2895
|
LRS.contentOpened = function(data) {
|
|
2895
2896
|
if (!TRACK_NAVIGATION) return;
|
|
2896
2897
|
|
|
@@ -2910,31 +2911,31 @@ function generateLrsBridgeCode(options) {
|
|
|
2910
2911
|
lessonId = lessonId.substring(2); // Remove '#/'
|
|
2911
2912
|
}
|
|
2912
2913
|
|
|
2913
|
-
//
|
|
2914
|
+
// Get the page title - prefer lesson name from DOM
|
|
2915
|
+
var pageTitle = data.title || lessonInfo.name || 'Page';
|
|
2916
|
+
|
|
2917
|
+
// Build page activity object with human-readable name
|
|
2918
|
+
// This shows the page/lesson title in the Object column
|
|
2919
|
+
var pageObject = buildPageActivityObject({
|
|
2920
|
+
pageGuid: lessonId,
|
|
2921
|
+
name: pageTitle,
|
|
2922
|
+
resourceType: 'Lesson'
|
|
2923
|
+
});
|
|
2924
|
+
|
|
2925
|
+
// Add page info to context extensions
|
|
2914
2926
|
var additionalContext = {
|
|
2915
2927
|
extensions: {
|
|
2916
2928
|
pageId: lessonId || 'home',
|
|
2917
|
-
pageTitle:
|
|
2929
|
+
pageTitle: pageTitle,
|
|
2918
2930
|
lessonName: lessonInfo.name,
|
|
2919
2931
|
sectionName: lessonInfo.sectionName,
|
|
2920
2932
|
pageUrl: data.url || window.location.href
|
|
2921
2933
|
}
|
|
2922
2934
|
};
|
|
2923
2935
|
|
|
2924
|
-
// Use
|
|
2925
|
-
//
|
|
2926
|
-
var statement =
|
|
2927
|
-
'experienced',
|
|
2928
|
-
'http://xyleme.com/bravais/activities/document',
|
|
2929
|
-
{
|
|
2930
|
-
event: 'page_viewed',
|
|
2931
|
-
pageId: lessonId,
|
|
2932
|
-
lessonName: lessonInfo.name,
|
|
2933
|
-
sectionName: lessonInfo.sectionName
|
|
2934
|
-
},
|
|
2935
|
-
result,
|
|
2936
|
-
additionalContext
|
|
2937
|
-
);
|
|
2936
|
+
// Use 'experienced' verb for viewing content
|
|
2937
|
+
// Parent course activity added by buildXylemeContext ensures document aggregation
|
|
2938
|
+
var statement = buildStatementXyleme('experienced', pageObject, result, additionalContext);
|
|
2938
2939
|
sendStatement(statement);
|
|
2939
2940
|
};
|
|
2940
2941
|
|
|
@@ -3386,6 +3387,9 @@ function generateLrsBridgeCode(options) {
|
|
|
3386
3387
|
function setupQuizInterceptors() {
|
|
3387
3388
|
if (!TRACK_QUIZZES) return;
|
|
3388
3389
|
|
|
3390
|
+
// Set up Knowledge Check specific interceptors for Rise blocks
|
|
3391
|
+
setupKnowledgeCheckInterceptors();
|
|
3392
|
+
|
|
3389
3393
|
var quizObserver = new MutationObserver(function(mutations) {
|
|
3390
3394
|
mutations.forEach(function(mutation) {
|
|
3391
3395
|
mutation.addedNodes.forEach(function(node) {
|
|
@@ -3590,6 +3594,162 @@ function generateLrsBridgeCode(options) {
|
|
|
3590
3594
|
});
|
|
3591
3595
|
}
|
|
3592
3596
|
|
|
3597
|
+
// Track submitted Knowledge Check blocks to avoid duplicates
|
|
3598
|
+
var submittedKnowledgeChecks = {};
|
|
3599
|
+
|
|
3600
|
+
/**
|
|
3601
|
+
* Set up interceptors specifically for Rise Knowledge Check blocks
|
|
3602
|
+
* These blocks have a different DOM structure than standard quiz results
|
|
3603
|
+
*/
|
|
3604
|
+
function setupKnowledgeCheckInterceptors() {
|
|
3605
|
+
if (!TRACK_QUIZZES) return;
|
|
3606
|
+
|
|
3607
|
+
// Intercept submit button clicks on Knowledge Check blocks
|
|
3608
|
+
document.addEventListener('click', function(e) {
|
|
3609
|
+
var submitBtn = e.target.closest('.quiz-card__button');
|
|
3610
|
+
if (!submitBtn) return;
|
|
3611
|
+
|
|
3612
|
+
// Find the Knowledge Check block
|
|
3613
|
+
var kcBlock = submitBtn.closest('[data-test-id="block-kc-card"]') ||
|
|
3614
|
+
submitBtn.closest('.block-knowledge');
|
|
3615
|
+
if (!kcBlock) return;
|
|
3616
|
+
|
|
3617
|
+
// Wait for feedback to appear after submission
|
|
3618
|
+
setTimeout(function() {
|
|
3619
|
+
extractKnowledgeCheckResult(kcBlock);
|
|
3620
|
+
}, 500);
|
|
3621
|
+
}, true);
|
|
3622
|
+
|
|
3623
|
+
log('Knowledge Check interceptors set up');
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
/**
|
|
3627
|
+
* Extract and send xAPI statement for a Knowledge Check submission
|
|
3628
|
+
*/
|
|
3629
|
+
function extractKnowledgeCheckResult(kcBlock) {
|
|
3630
|
+
// Get block ID for deduplication
|
|
3631
|
+
var blockContainer = kcBlock.closest('[data-block-id]');
|
|
3632
|
+
var blockId = blockContainer ? blockContainer.getAttribute('data-block-id') : null;
|
|
3633
|
+
|
|
3634
|
+
// Get question ID from the title element
|
|
3635
|
+
var questionTitleEl = kcBlock.querySelector('.quiz-card__title');
|
|
3636
|
+
var questionId = questionTitleEl ? questionTitleEl.id : (blockId ? 'q-' + blockId : 'q-' + generateUUID());
|
|
3637
|
+
|
|
3638
|
+
// Check if we already processed this submission (avoid duplicates)
|
|
3639
|
+
var submissionKey = blockId || questionId;
|
|
3640
|
+
var feedbackLabel = kcBlock.querySelector('.quiz-card__feedback-label');
|
|
3641
|
+
if (!feedbackLabel) {
|
|
3642
|
+
log('Knowledge Check: No feedback visible yet');
|
|
3643
|
+
return;
|
|
3644
|
+
}
|
|
3645
|
+
|
|
3646
|
+
var feedbackText = feedbackLabel.textContent.trim().toLowerCase();
|
|
3647
|
+
var submissionId = submissionKey + '-' + feedbackText;
|
|
3648
|
+
|
|
3649
|
+
if (submittedKnowledgeChecks[submissionId]) {
|
|
3650
|
+
log('Knowledge Check: Already processed this submission');
|
|
3651
|
+
return;
|
|
3652
|
+
}
|
|
3653
|
+
submittedKnowledgeChecks[submissionId] = true;
|
|
3654
|
+
|
|
3655
|
+
// Get question text
|
|
3656
|
+
var questionText = '';
|
|
3657
|
+
var questionTextEl = kcBlock.querySelector('.quiz-card__title .fr-view, .quiz-card__title');
|
|
3658
|
+
if (questionTextEl) {
|
|
3659
|
+
questionText = questionTextEl.textContent.trim();
|
|
3660
|
+
}
|
|
3661
|
+
|
|
3662
|
+
// Determine question type from aria-label
|
|
3663
|
+
var wrapper = kcBlock.querySelector('[data-test-id="block-knowledge-wrapper"]');
|
|
3664
|
+
var ariaLabel = wrapper ? wrapper.getAttribute('aria-label') : '';
|
|
3665
|
+
var questionType = 'unknown';
|
|
3666
|
+
if (ariaLabel.indexOf('Multiple choice') > -1) questionType = 'multiple-choice';
|
|
3667
|
+
else if (ariaLabel.indexOf('Multiple response') > -1) questionType = 'multiple-response';
|
|
3668
|
+
else if (ariaLabel.indexOf('Fill in the blank') > -1) questionType = 'fill-in-blank';
|
|
3669
|
+
else if (ariaLabel.indexOf('Matching') > -1) questionType = 'matching';
|
|
3670
|
+
|
|
3671
|
+
// Get selected answer(s) based on question type
|
|
3672
|
+
var answerText = extractKnowledgeCheckAnswer(kcBlock, questionType);
|
|
3673
|
+
|
|
3674
|
+
// Get correct/incorrect from feedback
|
|
3675
|
+
var isCorrect = feedbackText === 'correct';
|
|
3676
|
+
|
|
3677
|
+
// Get lesson context
|
|
3678
|
+
var lessonInfo = getCachedLessonInfo();
|
|
3679
|
+
|
|
3680
|
+
log('Knowledge Check submitted:', {
|
|
3681
|
+
questionId: questionId,
|
|
3682
|
+
questionText: questionText.substring(0, 50) + '...',
|
|
3683
|
+
questionType: questionType,
|
|
3684
|
+
answer: answerText.substring(0, 50) + '...',
|
|
3685
|
+
correct: isCorrect
|
|
3686
|
+
});
|
|
3687
|
+
|
|
3688
|
+
// Send question answered statement using existing LRS method
|
|
3689
|
+
LRS.questionAnswered({
|
|
3690
|
+
questionId: questionId,
|
|
3691
|
+
questionGuid: blockId || generateUUID(),
|
|
3692
|
+
questionNumber: 1,
|
|
3693
|
+
questionText: questionText.substring(0, 500),
|
|
3694
|
+
questionType: questionType,
|
|
3695
|
+
answer: answerText.substring(0, 500),
|
|
3696
|
+
correct: isCorrect,
|
|
3697
|
+
result: isCorrect ? 'correct' : 'incorrect',
|
|
3698
|
+
assessmentName: 'Knowledge Check',
|
|
3699
|
+
lessonName: lessonInfo.name,
|
|
3700
|
+
sectionName: lessonInfo.sectionName
|
|
3701
|
+
});
|
|
3702
|
+
}
|
|
3703
|
+
|
|
3704
|
+
/**
|
|
3705
|
+
* Extract the selected answer text from a Knowledge Check block
|
|
3706
|
+
* based on the question type
|
|
3707
|
+
*/
|
|
3708
|
+
function extractKnowledgeCheckAnswer(kcBlock, questionType) {
|
|
3709
|
+
var answerText = '';
|
|
3710
|
+
|
|
3711
|
+
if (questionType === 'multiple-choice') {
|
|
3712
|
+
// Find checked radio button
|
|
3713
|
+
var checkedInput = kcBlock.querySelector('.quiz-multiple-choice-option__input:checked');
|
|
3714
|
+
if (checkedInput) {
|
|
3715
|
+
var label = checkedInput.closest('.quiz-multiple-choice-option');
|
|
3716
|
+
var textEl = label ? label.querySelector('.quiz-multiple-choice-option__label .fr-view, .quiz-multiple-choice-option__label') : null;
|
|
3717
|
+
answerText = textEl ? textEl.textContent.trim() : '';
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
else if (questionType === 'multiple-response') {
|
|
3721
|
+
// Find all checked checkboxes
|
|
3722
|
+
var checkedInputs = kcBlock.querySelectorAll('.quiz-multiple-response-option__input:checked');
|
|
3723
|
+
var answers = [];
|
|
3724
|
+
checkedInputs.forEach(function(input) {
|
|
3725
|
+
var label = input.closest('.quiz-multiple-response-option');
|
|
3726
|
+
var textEl = label ? label.querySelector('.quiz-multiple-response-option__text .fr-view, .quiz-multiple-response-option__text') : null;
|
|
3727
|
+
if (textEl) answers.push(textEl.textContent.trim());
|
|
3728
|
+
});
|
|
3729
|
+
answerText = answers.join('; ');
|
|
3730
|
+
}
|
|
3731
|
+
else if (questionType === 'fill-in-blank') {
|
|
3732
|
+
// Get text input value
|
|
3733
|
+
var textInput = kcBlock.querySelector('.quiz-fill__input');
|
|
3734
|
+
answerText = textInput ? textInput.value.trim() : '';
|
|
3735
|
+
}
|
|
3736
|
+
else if (questionType === 'matching') {
|
|
3737
|
+
// Extract matching pairs from the drop zones
|
|
3738
|
+
var dropZones = kcBlock.querySelectorAll('.matching-drop-zone');
|
|
3739
|
+
var pairs = [];
|
|
3740
|
+
dropZones.forEach(function(zone) {
|
|
3741
|
+
var prompt = zone.querySelector('.matching-prompt-content');
|
|
3742
|
+
var response = zone.querySelector('.matching-interaction-piece-content');
|
|
3743
|
+
if (prompt && response) {
|
|
3744
|
+
pairs.push(prompt.textContent.trim() + ' \u2192 ' + response.textContent.trim());
|
|
3745
|
+
}
|
|
3746
|
+
});
|
|
3747
|
+
answerText = pairs.length > 0 ? pairs.join('; ') : 'Matching submitted';
|
|
3748
|
+
}
|
|
3749
|
+
|
|
3750
|
+
return answerText;
|
|
3751
|
+
}
|
|
3752
|
+
|
|
3593
3753
|
function setupInteractionInterceptors() {
|
|
3594
3754
|
if (!TRACK_INTERACTIONS) return;
|
|
3595
3755
|
|