@sunbird-cb/toc 0.0.21 โ 0.0.22
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/esm2022/lib/_collection/_common/content-toc/app-toc-content-card-v2/app-toc-content-card-v2.component.mjs +1 -61
- package/esm2022/lib/_collection/_common/content-toc/content-toc.component.mjs +1 -28
- package/esm2022/lib/components/app-toc-home-v2/app-toc-home-v2.component.mjs +1 -4
- package/esm2022/lib/services/app-toc-v2.service.mjs +1 -25
- package/esm2022/lib/services/app-toc.service.mjs +1 -230
- package/esm2022/lib/services/certificate.service.mjs +51 -9
- package/esm2022/lib/services/viewer-util.service.mjs +1 -54
- package/fesm2022/sunbird-cb-toc.mjs +50 -403
- package/fesm2022/sunbird-cb-toc.mjs.map +1 -1
- package/lib/_collection/_common/content-toc/app-toc-content-card-v2/app-toc-content-card-v2.component.d.ts.map +1 -1
- package/lib/_collection/_common/content-toc/content-toc.component.d.ts.map +1 -1
- package/lib/components/app-toc-home-v2/app-toc-home-v2.component.d.ts.map +1 -1
- package/lib/services/app-toc-v2.service.d.ts.map +1 -1
- package/lib/services/app-toc.service.d.ts +0 -52
- package/lib/services/app-toc.service.d.ts.map +1 -1
- package/lib/services/certificate.service.d.ts +4 -6
- package/lib/services/certificate.service.d.ts.map +1 -1
- package/lib/services/viewer-util.service.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -2045,17 +2045,6 @@ class AppTocService {
|
|
|
2045
2045
|
child.mimeType === 'application/vnd.sunbird.questionset';
|
|
2046
2046
|
if (isAssessment) {
|
|
2047
2047
|
}
|
|
2048
|
-
// Debug: Log when adding item with isPreAssessment flag to hashmap
|
|
2049
|
-
if (child.isPreAssessment === true) {
|
|
2050
|
-
console.log('๐ [HASHMAP BUILD] Adding pre-assessment to hashmap:', {
|
|
2051
|
-
id: child.identifier,
|
|
2052
|
-
name: child.name,
|
|
2053
|
-
isPreAssessment: localMap.isPreAssessment,
|
|
2054
|
-
parent: localMap.parent,
|
|
2055
|
-
completionStatus: localMap.completionStatus,
|
|
2056
|
-
status: localMap.status
|
|
2057
|
-
});
|
|
2058
|
-
}
|
|
2059
2048
|
this.hashmap[child.identifier] = localMap;
|
|
2060
2049
|
});
|
|
2061
2050
|
}
|
|
@@ -2100,7 +2089,6 @@ class AppTocService {
|
|
|
2100
2089
|
// 4. Different regular Course
|
|
2101
2090
|
const isNewContent = this.currentRootContentId !== hierarchyData.identifier;
|
|
2102
2091
|
if (isNewContent) {
|
|
2103
|
-
console.log(`๐งน [HASHMAP] Clearing hashmap - navigating from ${this.currentRootContentId} to ${hierarchyData.identifier}`);
|
|
2104
2092
|
this.hashmap = {};
|
|
2105
2093
|
this.currentRootContentId = hierarchyData.identifier;
|
|
2106
2094
|
}
|
|
@@ -2142,63 +2130,8 @@ class AppTocService {
|
|
|
2142
2130
|
this.hashmap = { ...this.hashmap };
|
|
2143
2131
|
}
|
|
2144
2132
|
}
|
|
2145
|
-
/**
|
|
2146
|
-
* Pre-compute milestone locking status for all milestones in Learning Pathway
|
|
2147
|
-
* This avoids expensive calculations in component getters
|
|
2148
|
-
*
|
|
2149
|
-
* Locking Rules:
|
|
2150
|
-
* 0. If user is not enrolled, ALL milestones are locked
|
|
2151
|
-
* 1. All milestones are locked by default
|
|
2152
|
-
* 2. Milestone 1 (M1) unlocks when pre-assessment is completed
|
|
2153
|
-
* 3. Milestone N (N > 1) unlocks when:
|
|
2154
|
-
* - All mandatory learning items in Milestone N-1 are completed
|
|
2155
|
-
* - The assessment of Milestone N-1 is completed
|
|
2156
|
-
*/
|
|
2157
|
-
/**
|
|
2158
|
-
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
2159
|
-
* LEARNING PATHWAY MILESTONE LOCKING SYSTEM - SINGLE SOURCE OF TRUTH
|
|
2160
|
-
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
2161
|
-
*
|
|
2162
|
-
* This method is the SINGLE SOURCE OF TRUTH for all milestone and assessment locking.
|
|
2163
|
-
* All locking logic is computed here and stored in the hashmap.
|
|
2164
|
-
* Components READ ONLY from the hashmap - they do NOT compute locks themselves.
|
|
2165
|
-
*
|
|
2166
|
-
* LOCKING RULES:
|
|
2167
|
-
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
2168
|
-
* 1. DEFAULT STATE: All milestones are LOCKED by default
|
|
2169
|
-
*
|
|
2170
|
-
* 2. MILESTONE 1 UNLOCKING:
|
|
2171
|
-
* - Unlocks when: Pre-assessment is 100% complete
|
|
2172
|
-
* - Lock message: "Complete the preliminary assessment to unlock this milestone"
|
|
2173
|
-
*
|
|
2174
|
-
* 3. MILESTONE N (N >= 2) UNLOCKING:
|
|
2175
|
-
* - Unlocks when: Previous milestone is 100% complete
|
|
2176
|
-
* - Previous milestone is complete when:
|
|
2177
|
-
* a) All MANDATORY courses are 100% complete
|
|
2178
|
-
* b) Milestone assessment is 100% complete
|
|
2179
|
-
* - Lock message: "Complete all mandatory content and assessment in Milestone N-1"
|
|
2180
|
-
*
|
|
2181
|
-
* 4. ASSESSMENT LOCKING (within unlocked milestones):
|
|
2182
|
-
* - Assessment locked until: All MANDATORY courses in SAME milestone complete
|
|
2183
|
-
* - Optional courses do NOT affect assessment locking
|
|
2184
|
-
* - Assessment lock message: "Complete all mandatory items to unlock the assessment"
|
|
2185
|
-
* - Once assessment is completed, it stays unlocked
|
|
2186
|
-
*
|
|
2187
|
-
* 5. PARENT MILESTONE LOCKING:
|
|
2188
|
-
* - All content inside locked milestone gets isParentMilestoneLocked = true
|
|
2189
|
-
* - This includes courses, assessments, nested resources
|
|
2190
|
-
*
|
|
2191
|
-
* 6. MANDATORY vs OPTIONAL:
|
|
2192
|
-
* - By default, ALL courses are mandatory (unless isMandatory: false)
|
|
2193
|
-
* - Optional courses do NOT block progression
|
|
2194
|
-
*
|
|
2195
|
-
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
2196
|
-
*/
|
|
2197
2133
|
computeMilestoneLockingStatus(isEnrolled = true) {
|
|
2198
|
-
console.log('๐ [MILESTONE LOCK] computeMilestoneLockingStatus CALLED with isEnrolled:', isEnrolled);
|
|
2199
|
-
console.log('๐ [MILESTONE LOCK] Hashmap size:', Object.keys(this.hashmap).length);
|
|
2200
2134
|
if (!this.hashmap || Object.keys(this.hashmap).length === 0) {
|
|
2201
|
-
console.warn('โ ๏ธ Hashmap is empty - cannot compute milestone locking');
|
|
2202
2135
|
return;
|
|
2203
2136
|
}
|
|
2204
2137
|
// STEP 1: Find all milestones and sort by index
|
|
@@ -2220,12 +2153,8 @@ class AppTocService {
|
|
|
2220
2153
|
if (milestoneEntries.length === 0) {
|
|
2221
2154
|
return;
|
|
2222
2155
|
}
|
|
2223
|
-
milestoneEntries.forEach((id, i) => {
|
|
2224
|
-
console.log(` M${i + 1}: ${this.hashmap[id].name || id}`);
|
|
2225
|
-
});
|
|
2226
2156
|
// STEP 2: If user NOT enrolled, lock ALL milestones and children
|
|
2227
2157
|
if (!isEnrolled) {
|
|
2228
|
-
console.log('\nโ ๏ธ User NOT enrolled - locking ALL milestones and children');
|
|
2229
2158
|
milestoneEntries.forEach(milestoneId => {
|
|
2230
2159
|
this.hashmap[milestoneId].computedIsLocked = true;
|
|
2231
2160
|
this.hashmap[milestoneId].unlockMessage = 'Enroll in this course to access milestones';
|
|
@@ -2242,7 +2171,6 @@ class AppTocService {
|
|
|
2242
2171
|
}
|
|
2243
2172
|
// STEP 3: Check pre-assessment completion
|
|
2244
2173
|
const isPreAssessmentCompleted = this.checkPreAssessmentCompletion();
|
|
2245
|
-
console.log('๐ [MILESTONE LOCK] Pre-assessment completed:', isPreAssessmentCompleted ? 'โ
YES' : 'โ NO');
|
|
2246
2174
|
// STEP 4: Compute locking for each milestone
|
|
2247
2175
|
milestoneEntries.forEach((milestoneId, index) => {
|
|
2248
2176
|
const milestone = this.hashmap[milestoneId];
|
|
@@ -2255,17 +2183,11 @@ class AppTocService {
|
|
|
2255
2183
|
this.hashmap[milestoneId].computedIsLocked = isLocked;
|
|
2256
2184
|
this.hashmap[milestoneId].unlockMessage = isLocked ?
|
|
2257
2185
|
'Complete the preliminary assessment to unlock this milestone' : '';
|
|
2258
|
-
console.log(`๐ [MILESTONE 1] ${milestone.name}:`, {
|
|
2259
|
-
isPreAssessmentCompleted,
|
|
2260
|
-
isLocked: isLocked ? '๐ LOCKED' : '๐ UNLOCKED',
|
|
2261
|
-
unlockMessage: this.hashmap[milestoneId].unlockMessage
|
|
2262
|
-
});
|
|
2263
2186
|
// For unlocked M1, check assessment locking
|
|
2264
2187
|
if (!isLocked) {
|
|
2265
2188
|
this.computeAssessmentLockingInMilestone(milestoneId);
|
|
2266
2189
|
}
|
|
2267
2190
|
else {
|
|
2268
|
-
console.log(` โจฏ Milestone locked - marking all children as parent-locked`);
|
|
2269
2191
|
this.markMilestoneChildrenAsParentLocked(milestoneId, true);
|
|
2270
2192
|
}
|
|
2271
2193
|
return;
|
|
@@ -2280,63 +2202,39 @@ class AppTocService {
|
|
|
2280
2202
|
const prevStatus = Number(previousMilestone.status) || 0;
|
|
2281
2203
|
const prevCompletedLeafNodes = Number(previousMilestone.completedLeafNodesCount) || 0;
|
|
2282
2204
|
const prevLeafNodesCount = Number(previousMilestone.leafNodesCount) || 0;
|
|
2283
|
-
console.log(`๐ [MILESTONE ${milestoneNum}] Checking if previous M${index} is complete:`, {
|
|
2284
|
-
previousMilestoneName: previousMilestone.name,
|
|
2285
|
-
completionPercentage: prevCompletionPct,
|
|
2286
|
-
completionStatus: prevCompletionStatus,
|
|
2287
|
-
status: prevStatus,
|
|
2288
|
-
completedLeafNodes: prevCompletedLeafNodes,
|
|
2289
|
-
leafNodesCount: prevLeafNodesCount
|
|
2290
|
-
});
|
|
2291
2205
|
let previousMilestoneComplete = prevCompletionPct >= 100 ||
|
|
2292
2206
|
prevCompletionStatus === 2 ||
|
|
2293
2207
|
prevStatus === 2 ||
|
|
2294
2208
|
(prevLeafNodesCount > 0 && prevCompletedLeafNodes >= prevLeafNodesCount);
|
|
2295
|
-
console.log(` Primary check result: ${previousMilestoneComplete ? 'โ
COMPLETE' : 'โ INCOMPLETE'}`);
|
|
2296
2209
|
// Fallback: Check individual items
|
|
2297
2210
|
if (!previousMilestoneComplete) {
|
|
2298
|
-
console.log(` Running fallback check (mandatory content + assessment)...`);
|
|
2299
2211
|
const isPreviousMilestoneAssessmentComplete = this.checkMilestoneAssessmentComplete(previousMilestoneId);
|
|
2300
2212
|
const isPreviousMilestoneMandatoryComplete = this.checkMilestoneMandatoryContentComplete(previousMilestoneId);
|
|
2301
2213
|
previousMilestoneComplete = isPreviousMilestoneAssessmentComplete && isPreviousMilestoneMandatoryComplete;
|
|
2302
|
-
console.log(` Fallback check: mandatory=${isPreviousMilestoneMandatoryComplete}, assessment=${isPreviousMilestoneAssessmentComplete}, result=${previousMilestoneComplete}`);
|
|
2303
2214
|
}
|
|
2304
2215
|
const isLocked = !previousMilestoneComplete;
|
|
2305
2216
|
this.hashmap[milestoneId].computedIsLocked = isLocked;
|
|
2306
2217
|
this.hashmap[milestoneId].unlockMessage = isLocked ?
|
|
2307
2218
|
`Complete all mandatory content and assessment in Milestone ${index} to unlock this milestone` : '';
|
|
2308
|
-
console.log(` ๐ [MILESTONE ${milestoneNum}] ${milestone.name}:`, {
|
|
2309
|
-
previousMilestoneComplete: previousMilestoneComplete ? 'โ
YES' : 'โ NO',
|
|
2310
|
-
isLocked: isLocked ? '๐ LOCKED' : '๐ UNLOCKED',
|
|
2311
|
-
unlockMessage: this.hashmap[milestoneId].unlockMessage
|
|
2312
|
-
});
|
|
2313
2219
|
// For unlocked milestones, check assessment locking
|
|
2314
2220
|
if (!isLocked) {
|
|
2315
2221
|
this.computeAssessmentLockingInMilestone(milestoneId);
|
|
2316
2222
|
}
|
|
2317
2223
|
else {
|
|
2318
|
-
console.log(` โจฏ Milestone locked - marking all children as parent-locked`);
|
|
2319
2224
|
this.markMilestoneChildrenAsParentLocked(milestoneId, true);
|
|
2320
2225
|
}
|
|
2321
2226
|
}
|
|
2322
2227
|
else {
|
|
2323
2228
|
this.hashmap[milestoneId].computedIsLocked = true;
|
|
2324
2229
|
this.hashmap[milestoneId].unlockMessage = 'Previous milestone not found';
|
|
2325
|
-
console.log(` ๐ LOCKED (previous milestone not found)`);
|
|
2326
2230
|
}
|
|
2327
2231
|
});
|
|
2328
2232
|
// STEP 4.5: Debug log milestone leaf nodes and their completion status
|
|
2329
|
-
console.log('\n๐ Milestone Leaf Nodes Completion Status:');
|
|
2330
2233
|
milestoneEntries.forEach((milestoneId, index) => {
|
|
2331
2234
|
const milestone = this.hashmap[milestoneId];
|
|
2332
2235
|
if (!milestone)
|
|
2333
2236
|
return;
|
|
2334
|
-
console.log(` Leaf Nodes Array:`, milestone.leafNodes);
|
|
2335
|
-
console.log(` Leaf Nodes Count: ${milestone.leafNodesCount}`);
|
|
2336
|
-
console.log(` Completed Leaf Nodes Count: ${milestone.completedLeafNodesCount || 0}`);
|
|
2337
|
-
console.log(` Completion %: ${milestone.completionPercentage}%`);
|
|
2338
2237
|
if (milestone.leafNodes && milestone.leafNodes.length > 0) {
|
|
2339
|
-
console.log(` Individual Leaf Node Status:`);
|
|
2340
2238
|
milestone.leafNodes.forEach((leafId, i) => {
|
|
2341
2239
|
const leafData = this.hashmap[leafId];
|
|
2342
2240
|
if (leafData) {
|
|
@@ -2344,26 +2242,11 @@ class AppTocService {
|
|
|
2344
2242
|
leafData.status === 2 ||
|
|
2345
2243
|
(leafData.completionPercentage && leafData.completionPercentage >= 100) ||
|
|
2346
2244
|
(leafData.progress && leafData.progress >= 100);
|
|
2347
|
-
console.log(` ${i + 1}. ${leafData.name || leafId} [${leafData.primaryCategory}]:`, {
|
|
2348
|
-
id: leafId,
|
|
2349
|
-
completionStatus: leafData.completionStatus,
|
|
2350
|
-
status: leafData.status,
|
|
2351
|
-
completionPercentage: leafData.completionPercentage,
|
|
2352
|
-
progress: leafData.progress,
|
|
2353
|
-
isComplete: isComplete ? 'โ
' : 'โ'
|
|
2354
|
-
});
|
|
2355
|
-
}
|
|
2356
|
-
else {
|
|
2357
|
-
console.log(` ${i + 1}. โ ๏ธ Leaf node ${leafId} NOT FOUND in hashmap`);
|
|
2358
2245
|
}
|
|
2359
2246
|
});
|
|
2360
2247
|
}
|
|
2361
|
-
else {
|
|
2362
|
-
console.log(` โ ๏ธ No leaf nodes defined for this milestone`);
|
|
2363
|
-
}
|
|
2364
2248
|
});
|
|
2365
2249
|
// STEP 5: Compute parent milestone lock status for ALL children
|
|
2366
|
-
console.log('\n๐ Computing parent milestone locks for all children...');
|
|
2367
2250
|
Object.keys(this.hashmap).forEach(key => {
|
|
2368
2251
|
const item = this.hashmap[key];
|
|
2369
2252
|
if (item.isMilestone)
|
|
@@ -2392,19 +2275,11 @@ class AppTocService {
|
|
|
2392
2275
|
this.hashmap[key].isParentMilestoneLocked = false;
|
|
2393
2276
|
}
|
|
2394
2277
|
});
|
|
2395
|
-
// STEP 6: Trigger hashmap update
|
|
2396
|
-
console.log('โ
Milestone locking computation COMPLETE');
|
|
2397
2278
|
// Debug: Log final lock status for all milestones
|
|
2398
2279
|
const milestonesFinal = Object.keys(this.hashmap).filter(key => this.hashmap[key].isMilestone ||
|
|
2399
2280
|
this.hashmap[key].primaryCategory === 'Milestone' ||
|
|
2400
2281
|
this.hashmap[key].courseCategory === 'Milestone');
|
|
2401
|
-
console.log('๐ [FINAL LOCK STATUS] All milestones:');
|
|
2402
|
-
milestonesFinal.forEach((id, i) => {
|
|
2403
|
-
const m = this.hashmap[id];
|
|
2404
|
-
console.log(` ${i + 1}. ${m.name}: computedIsLocked=${m.computedIsLocked}, unlockMessage="${m.unlockMessage || 'N/A'}"`);
|
|
2405
|
-
});
|
|
2406
2282
|
this.hashmap = { ...this.hashmap };
|
|
2407
|
-
console.log('๐ก [SERVICE] Broadcasting hashmap update with computedIsLocked values');
|
|
2408
2283
|
this.hashmapUpdated.next({ timestamp: Date.now(), hashmap: this.hashmap });
|
|
2409
2284
|
}
|
|
2410
2285
|
/**
|
|
@@ -2412,27 +2287,21 @@ class AppTocService {
|
|
|
2412
2287
|
* Called from viewer-util.service.ts after progress updates
|
|
2413
2288
|
*/
|
|
2414
2289
|
triggerMilestoneLockUpdate() {
|
|
2415
|
-
console.log('๐ [TRIGGER] triggerMilestoneLockUpdate called');
|
|
2416
2290
|
// Check if we have a Learning Pathway in the hashmap
|
|
2417
2291
|
const hasLearningPathway = Object.keys(this.hashmap).some(key => {
|
|
2418
2292
|
const item = this.hashmap[key];
|
|
2419
2293
|
// Check using OR condition - either flag indicates Learning Pathway
|
|
2420
2294
|
return item.isLearningPathway === true || item.courseCategory === 'Learning Pathway';
|
|
2421
2295
|
});
|
|
2422
|
-
console.log(` Is Learning Pathway: ${hasLearningPathway}`);
|
|
2423
2296
|
if (hasLearningPathway) {
|
|
2424
|
-
console.log('๐ [TRIGGER] Triggering milestone lock recomputation after progress update');
|
|
2425
2297
|
// Assume enrolled since progress was just updated
|
|
2426
2298
|
this.computeMilestoneLockingStatus(true);
|
|
2427
2299
|
}
|
|
2428
2300
|
else {
|
|
2429
|
-
console.log('๐ [TRIGGER] Regular content - emitting hashmap update for top-bar refresh');
|
|
2430
2301
|
// For regular content (non-Learning Pathway), just emit the hashmap update
|
|
2431
2302
|
// so the top-bar component can recalculate the completion count
|
|
2432
2303
|
this.hashmap = { ...this.hashmap };
|
|
2433
|
-
console.log('๐ก [TRIGGER] Broadcasting hashmap update event');
|
|
2434
2304
|
this.hashmapUpdated.next({ timestamp: Date.now(), hashmap: this.hashmap });
|
|
2435
|
-
console.log('โ
[TRIGGER] Hashmap update broadcasted');
|
|
2436
2305
|
}
|
|
2437
2306
|
}
|
|
2438
2307
|
/**
|
|
@@ -2440,8 +2309,6 @@ class AppTocService {
|
|
|
2440
2309
|
* Pre-assessment is typically a Course Assessment at the root level of Learning Pathway (before milestones)
|
|
2441
2310
|
*/
|
|
2442
2311
|
checkPreAssessmentCompletion() {
|
|
2443
|
-
console.log('๐ [PRE-ASSESSMENT] Starting pre-assessment completion check');
|
|
2444
|
-
console.log('๐ [PRE-ASSESSMENT] Hashmap keys:', Object.keys(this.hashmap).length);
|
|
2445
2312
|
// Find the Learning Pathway root - check multiple conditions
|
|
2446
2313
|
let learningPathwayId = null;
|
|
2447
2314
|
for (const key of Object.keys(this.hashmap)) {
|
|
@@ -2451,36 +2318,17 @@ class AppTocService {
|
|
|
2451
2318
|
item.isLearningPathway === true ||
|
|
2452
2319
|
(item.primaryCategory === 'Blended Program' && item.courseCategory === 'Learning Pathway')) {
|
|
2453
2320
|
learningPathwayId = key;
|
|
2454
|
-
console.log('๐ [PRE-ASSESSMENT] Found Learning Pathway root:', key, item.name);
|
|
2455
2321
|
break;
|
|
2456
2322
|
}
|
|
2457
2323
|
}
|
|
2458
2324
|
if (!learningPathwayId) {
|
|
2459
|
-
console.log('โ ๏ธ [PRE-ASSESSMENT] Learning Pathway root NOT FOUND - returning false to keep milestones locked');
|
|
2460
2325
|
return false;
|
|
2461
2326
|
}
|
|
2462
|
-
// Step 1: Look for items explicitly marked as pre-assessment (isPreAssessment flag)
|
|
2463
|
-
console.log('๐ [PRE-ASSESSMENT] Step 1: Looking for items with isPreAssessment=true flag...');
|
|
2464
|
-
console.log('๐ [PRE-ASSESSMENT] Dumping all hashmap items for debugging:');
|
|
2465
|
-
for (const key of Object.keys(this.hashmap)) {
|
|
2466
|
-
const item = this.hashmap[key];
|
|
2467
|
-
if (item.isPreAssessment || item.primaryCategory === 'Course Assessment' || item.primaryCategory === 'Standalone Assessment') {
|
|
2468
|
-
console.log(` ๐ ${key}: isPreAssessment=${item.isPreAssessment}, primaryCategory=${item.primaryCategory}, parent=${item.parent}, completionStatus=${item.completionStatus}, status=${item.status}, completionPercentage=${item.completionPercentage}`);
|
|
2469
|
-
}
|
|
2470
|
-
}
|
|
2471
2327
|
let foundPreAssessmentFlag = false;
|
|
2472
2328
|
for (const key of Object.keys(this.hashmap)) {
|
|
2473
2329
|
const item = this.hashmap[key];
|
|
2474
2330
|
if (item.isPreAssessment === true) {
|
|
2475
2331
|
foundPreAssessmentFlag = true;
|
|
2476
|
-
console.log('๐ [PRE-ASSESSMENT] Found item with isPreAssessment=true:', {
|
|
2477
|
-
id: key,
|
|
2478
|
-
name: item.name,
|
|
2479
|
-
completionStatus: item.completionStatus,
|
|
2480
|
-
status: item.status,
|
|
2481
|
-
completionPercentage: item.completionPercentage,
|
|
2482
|
-
progress: item.progress
|
|
2483
|
-
});
|
|
2484
2332
|
// STRICT CHECK: Only return true if completionStatus is EXACTLY 2 (not undefined, null, or 0)
|
|
2485
2333
|
// completionPercentage check must be >= 100 AND be a number
|
|
2486
2334
|
const completionStatus = Number(item.completionStatus);
|
|
@@ -2490,20 +2338,10 @@ class AppTocService {
|
|
|
2490
2338
|
const isCompleted = (completionStatus === 2 || status === 2 ||
|
|
2491
2339
|
(completionPercentage >= 100 && !isNaN(completionPercentage)) ||
|
|
2492
2340
|
(progress >= 100 && !isNaN(progress)));
|
|
2493
|
-
console.log('๐ [PRE-ASSESSMENT] Pre-assessment completion result:', isCompleted ? 'โ
COMPLETED' : 'โ NOT COMPLETED', {
|
|
2494
|
-
completionStatusCheck: completionStatus === 2,
|
|
2495
|
-
statusCheck: status === 2,
|
|
2496
|
-
completionPercentageCheck: completionPercentage >= 100,
|
|
2497
|
-
progressCheck: progress >= 100
|
|
2498
|
-
});
|
|
2499
2341
|
return isCompleted;
|
|
2500
2342
|
}
|
|
2501
2343
|
}
|
|
2502
|
-
if (!foundPreAssessmentFlag) {
|
|
2503
|
-
console.log('โ ๏ธ [PRE-ASSESSMENT] No item with isPreAssessment=true found in hashmap');
|
|
2504
|
-
}
|
|
2505
2344
|
// Step 2: Fallback - Look for Course Assessment that is a direct child of Learning Pathway (not a milestone child)
|
|
2506
|
-
console.log('๐ [PRE-ASSESSMENT] Step 2: Looking for Course Assessment direct child of Learning Pathway...');
|
|
2507
2345
|
for (const key of Object.keys(this.hashmap)) {
|
|
2508
2346
|
const item = this.hashmap[key];
|
|
2509
2347
|
// Must be a direct child of the Learning Pathway
|
|
@@ -2515,14 +2353,6 @@ class AppTocService {
|
|
|
2515
2353
|
// Must be a Course Assessment or Standalone Assessment
|
|
2516
2354
|
if (item.primaryCategory !== 'Course Assessment' && item.primaryCategory !== 'Standalone Assessment')
|
|
2517
2355
|
continue;
|
|
2518
|
-
console.log('๐ [PRE-ASSESSMENT] Found Course Assessment child of Learning Pathway:', {
|
|
2519
|
-
id: key,
|
|
2520
|
-
name: item.name,
|
|
2521
|
-
primaryCategory: item.primaryCategory,
|
|
2522
|
-
completionStatus: item.completionStatus,
|
|
2523
|
-
status: item.status,
|
|
2524
|
-
completionPercentage: item.completionPercentage
|
|
2525
|
-
});
|
|
2526
2356
|
// STRICT CHECK: Only return true if completionStatus is EXACTLY 2
|
|
2527
2357
|
const completionStatus = Number(item.completionStatus);
|
|
2528
2358
|
const status = Number(item.status);
|
|
@@ -2531,16 +2361,9 @@ class AppTocService {
|
|
|
2531
2361
|
const isCompleted = (completionStatus === 2 || status === 2 ||
|
|
2532
2362
|
(completionPercentage >= 100 && !isNaN(completionPercentage)) ||
|
|
2533
2363
|
(progress >= 100 && !isNaN(progress)));
|
|
2534
|
-
console.log('๐ [PRE-ASSESSMENT] Course Assessment completion result:', isCompleted ? 'โ
COMPLETED' : 'โ NOT COMPLETED', {
|
|
2535
|
-
completionStatusCheck: completionStatus === 2,
|
|
2536
|
-
statusCheck: status === 2,
|
|
2537
|
-
completionPercentageCheck: completionPercentage >= 100,
|
|
2538
|
-
progressCheck: progress >= 100
|
|
2539
|
-
});
|
|
2540
2364
|
return isCompleted;
|
|
2541
2365
|
}
|
|
2542
2366
|
// Step 3: If no pre-assessment found at all, keep milestones LOCKED (fail-safe)
|
|
2543
|
-
console.log('โ ๏ธ [PRE-ASSESSMENT] No pre-assessment found in hashmap - returning FALSE to keep milestones LOCKED');
|
|
2544
2367
|
return false;
|
|
2545
2368
|
}
|
|
2546
2369
|
/**
|
|
@@ -2552,7 +2375,6 @@ class AppTocService {
|
|
|
2552
2375
|
const milestone = this.hashmap[milestoneId];
|
|
2553
2376
|
let foundMilestoneAssessment = false;
|
|
2554
2377
|
let isMilestoneAssessmentComplete = false;
|
|
2555
|
-
console.log(`๐ Checking milestone assessment for: ${milestoneId}`);
|
|
2556
2378
|
// Check all items in hashmap that are DIRECT children of this milestone
|
|
2557
2379
|
for (const key of Object.keys(this.hashmap)) {
|
|
2558
2380
|
const item = this.hashmap[key];
|
|
@@ -2568,14 +2390,6 @@ class AppTocService {
|
|
|
2568
2390
|
// Found the milestone assessment
|
|
2569
2391
|
foundMilestoneAssessment = true;
|
|
2570
2392
|
const isCompleted = item.completionStatus === 2 || item.status === 2 || item.completionPercentage >= 100 || item.progress >= 100;
|
|
2571
|
-
console.log(`๐ Found milestone assessment (direct child): ${item.name || key}`, {
|
|
2572
|
-
milestoneId,
|
|
2573
|
-
assessmentId: key,
|
|
2574
|
-
completionStatus: item.completionStatus,
|
|
2575
|
-
status: item.status,
|
|
2576
|
-
completionPercentage: item.completionPercentage,
|
|
2577
|
-
isCompleted
|
|
2578
|
-
});
|
|
2579
2393
|
if (isCompleted) {
|
|
2580
2394
|
isMilestoneAssessmentComplete = true;
|
|
2581
2395
|
}
|
|
@@ -2585,10 +2399,8 @@ class AppTocService {
|
|
|
2585
2399
|
// - If NO milestone assessment found โ consider complete (no assessment requirement)
|
|
2586
2400
|
// - If milestone assessment found โ it must be completed
|
|
2587
2401
|
if (!foundMilestoneAssessment) {
|
|
2588
|
-
console.log(`โน๏ธ No milestone assessment (direct child) found for ${milestoneId} - considering as complete`);
|
|
2589
2402
|
return true;
|
|
2590
2403
|
}
|
|
2591
|
-
console.log(`${isMilestoneAssessmentComplete ? 'โ
' : 'โ'} Milestone ${milestoneId} assessment: ${isMilestoneAssessmentComplete ? 'COMPLETE' : 'INCOMPLETE'}`);
|
|
2592
2404
|
return isMilestoneAssessmentComplete;
|
|
2593
2405
|
}
|
|
2594
2406
|
/**
|
|
@@ -2599,7 +2411,6 @@ class AppTocService {
|
|
|
2599
2411
|
const milestone = this.hashmap[milestoneId];
|
|
2600
2412
|
let mandatoryCount = 0;
|
|
2601
2413
|
let completedMandatoryCount = 0;
|
|
2602
|
-
console.log(`๐ Checking mandatory content for milestone: ${milestoneId}`);
|
|
2603
2414
|
// Check all items in hashmap that are direct children of this milestone (courses)
|
|
2604
2415
|
for (const key of Object.keys(this.hashmap)) {
|
|
2605
2416
|
const item = this.hashmap[key];
|
|
@@ -2623,25 +2434,12 @@ class AppTocService {
|
|
|
2623
2434
|
if (isMandatory) {
|
|
2624
2435
|
mandatoryCount++;
|
|
2625
2436
|
const isCompleted = item.completionStatus === 2 || item.status === 2 || item.completionPercentage >= 100 || item.progress >= 100;
|
|
2626
|
-
console.log(` ๐ Mandatory item: ${item.name || key}`, {
|
|
2627
|
-
isMandatory: item.isMandatory,
|
|
2628
|
-
completionStatus: item.completionStatus,
|
|
2629
|
-
status: item.status,
|
|
2630
|
-
completionPercentage: item.completionPercentage,
|
|
2631
|
-
progress: item.progress,
|
|
2632
|
-
isCompleted,
|
|
2633
|
-
hasCompletionStatus: item.completionStatus !== undefined,
|
|
2634
|
-
hasStatus: item.status !== undefined,
|
|
2635
|
-
hasCompletionPercentage: item.completionPercentage !== undefined,
|
|
2636
|
-
hasProgress: item.progress !== undefined
|
|
2637
|
-
});
|
|
2638
2437
|
if (isCompleted) {
|
|
2639
2438
|
completedMandatoryCount++;
|
|
2640
2439
|
}
|
|
2641
2440
|
}
|
|
2642
2441
|
}
|
|
2643
2442
|
const allComplete = mandatoryCount === 0 || completedMandatoryCount >= mandatoryCount;
|
|
2644
|
-
console.log(`๐ Milestone ${milestoneId} mandatory status: ${completedMandatoryCount}/${mandatoryCount} complete = ${allComplete ? 'โ
ALL COMPLETE' : 'โ INCOMPLETE'}`);
|
|
2645
2443
|
return allComplete;
|
|
2646
2444
|
}
|
|
2647
2445
|
/**
|
|
@@ -2670,7 +2468,6 @@ class AppTocService {
|
|
|
2670
2468
|
const milestone = this.hashmap[milestoneId];
|
|
2671
2469
|
if (!milestone)
|
|
2672
2470
|
return;
|
|
2673
|
-
console.log(`Computing assessment locking for milestone: ${milestoneId}`);
|
|
2674
2471
|
// Find assessment in this milestone
|
|
2675
2472
|
let assessmentId = null;
|
|
2676
2473
|
let assessment = null;
|
|
@@ -2686,12 +2483,10 @@ class AppTocService {
|
|
|
2686
2483
|
if (isAssessment) {
|
|
2687
2484
|
assessmentId = key;
|
|
2688
2485
|
assessment = item;
|
|
2689
|
-
console.log(`โ
Found milestone assessment: ${item.name} (${key})`);
|
|
2690
2486
|
break;
|
|
2691
2487
|
}
|
|
2692
2488
|
}
|
|
2693
2489
|
if (!assessmentId || !assessment) {
|
|
2694
|
-
console.log(`No assessment found in milestone ${milestoneId}`);
|
|
2695
2490
|
return;
|
|
2696
2491
|
}
|
|
2697
2492
|
// Check if assessment is already completed - re-read from hashmap to get latest data
|
|
@@ -2703,7 +2498,6 @@ class AppTocService {
|
|
|
2703
2498
|
// This ensures assessment is unlocked as soon as all mandatory courses are done
|
|
2704
2499
|
let mandatoryCount = 0;
|
|
2705
2500
|
let completedMandatoryCount = 0;
|
|
2706
|
-
console.log(`[ASSESSMENT LOCK CHECK] Checking mandatory courses for milestone: ${milestoneId}`);
|
|
2707
2501
|
for (const key of Object.keys(this.hashmap)) {
|
|
2708
2502
|
const item = this.hashmap[key];
|
|
2709
2503
|
if (key === assessmentId)
|
|
@@ -2731,44 +2525,22 @@ class AppTocService {
|
|
|
2731
2525
|
item.status === 2 ||
|
|
2732
2526
|
item.completionPercentage >= 100 ||
|
|
2733
2527
|
item.progress >= 100;
|
|
2734
|
-
console.log(` Course: ${item.name}`, {
|
|
2735
|
-
isMandatory,
|
|
2736
|
-
completionStatus: item.completionStatus,
|
|
2737
|
-
status: item.status,
|
|
2738
|
-
completionPercentage: item.completionPercentage,
|
|
2739
|
-
progress: item.progress,
|
|
2740
|
-
isCompleted
|
|
2741
|
-
});
|
|
2742
2528
|
if (isCompleted) {
|
|
2743
2529
|
completedMandatoryCount++;
|
|
2744
2530
|
}
|
|
2745
2531
|
}
|
|
2746
2532
|
}
|
|
2747
2533
|
const allMandatoryComplete = mandatoryCount === 0 || completedMandatoryCount >= mandatoryCount;
|
|
2748
|
-
console.log(`[ASSESSMENT LOCK CHECK] Summary:`, {
|
|
2749
|
-
mandatoryCount,
|
|
2750
|
-
completedMandatoryCount,
|
|
2751
|
-
allMandatoryComplete,
|
|
2752
|
-
assessmentCompleted,
|
|
2753
|
-
willUnlock: assessmentCompleted || allMandatoryComplete
|
|
2754
|
-
});
|
|
2755
2534
|
if (assessmentCompleted || allMandatoryComplete) {
|
|
2756
2535
|
this.hashmap[assessmentId].isAssessmentLocked = false;
|
|
2757
2536
|
this.hashmap[assessmentId].milestoneAssessmentLocked = false;
|
|
2758
2537
|
this.hashmap[assessmentId].assessmentLockMessage = '';
|
|
2759
|
-
console.log(`โ
Assessment ${assessmentId} is UNLOCKED (completed or all mandatory done)`);
|
|
2760
2538
|
return;
|
|
2761
2539
|
}
|
|
2762
2540
|
// If not unlocked, lock the assessment
|
|
2763
2541
|
this.hashmap[assessmentId].isAssessmentLocked = true;
|
|
2764
2542
|
this.hashmap[assessmentId].milestoneAssessmentLocked = true;
|
|
2765
2543
|
this.hashmap[assessmentId].assessmentLockMessage = 'This content is locked. Complete all mandatory items to unlock the assessment.';
|
|
2766
|
-
console.log(`๐ Assessment ${assessmentId} is LOCKED:`, {
|
|
2767
|
-
mandatoryCount,
|
|
2768
|
-
completedMandatoryCount,
|
|
2769
|
-
isLocked: true,
|
|
2770
|
-
milestoneAssessmentLocked: true
|
|
2771
|
-
});
|
|
2772
2544
|
}
|
|
2773
2545
|
/**
|
|
2774
2546
|
* Mark all children of a milestone as parent-locked or unlocked
|
|
@@ -2886,7 +2658,6 @@ class AppTocService {
|
|
|
2886
2658
|
}
|
|
2887
2659
|
}
|
|
2888
2660
|
setTranscriptionData(data) {
|
|
2889
|
-
// console.log('data--', data)
|
|
2890
2661
|
this.transriptionDataSubject.next(data);
|
|
2891
2662
|
}
|
|
2892
2663
|
setActiveSubtitleLanguage(activeLang) {
|
|
@@ -6286,6 +6057,17 @@ i0.ษตษตngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
6286
6057
|
* Certificate Service
|
|
6287
6058
|
* Handles certificate-related operations
|
|
6288
6059
|
*/
|
|
6060
|
+
const urls = {
|
|
6061
|
+
HIERARCHY: 'course/v1/hierarchy',
|
|
6062
|
+
LEARNER_PREFIX: '/api/',
|
|
6063
|
+
PROXIES_PREFIX: '/apis/proxies/v8/',
|
|
6064
|
+
VALIDATE_CERTIFICATE: 'certreg/v1/certs/validate',
|
|
6065
|
+
DOWNLOAD_CERTIFICATE: (id) => `certreg/v2/certs/download/${id}`,
|
|
6066
|
+
DOWNLOAD_CERTIFICATE_v2: (id) => `apis/protected/v8/cohorts/course/batch/cert/download/${id}`,
|
|
6067
|
+
SEARCH_CERTIFICATE: 'certreg/v1/certs/search',
|
|
6068
|
+
VALIDATE_ENROLLMENT: 'cios-enroll/v1/validation',
|
|
6069
|
+
CONSENT_API: 'consent/v1/acknowledge',
|
|
6070
|
+
};
|
|
6289
6071
|
class CertificateService {
|
|
6290
6072
|
constructor(http) {
|
|
6291
6073
|
this.http = http;
|
|
@@ -6301,7 +6083,7 @@ class CertificateService {
|
|
|
6301
6083
|
* Download certificate
|
|
6302
6084
|
*/
|
|
6303
6085
|
downloadCertificate(certId) {
|
|
6304
|
-
return this.http.get(
|
|
6086
|
+
return this.http.get(`${urls.LEARNER_PREFIX}${urls.DOWNLOAD_CERTIFICATE(certId)}`, {
|
|
6305
6087
|
responseType: 'blob'
|
|
6306
6088
|
});
|
|
6307
6089
|
}
|
|
@@ -6321,25 +6103,57 @@ class CertificateService {
|
|
|
6321
6103
|
* Download certificate v2
|
|
6322
6104
|
*/
|
|
6323
6105
|
downloadCertificate_v2(certId) {
|
|
6324
|
-
return this.http.get(
|
|
6325
|
-
responseType: 'blob'
|
|
6326
|
-
});
|
|
6106
|
+
return this.http.get(`${urls.DOWNLOAD_CERTIFICATE_v2(certId)}`);
|
|
6327
6107
|
}
|
|
6328
6108
|
/**
|
|
6329
6109
|
* Validate enrollment eligibility
|
|
6330
6110
|
*/
|
|
6331
|
-
validateEnrollmentEligibility(
|
|
6332
|
-
|
|
6111
|
+
validateEnrollmentEligibility(courseId, partnerId) {
|
|
6112
|
+
const option = {
|
|
6113
|
+
url: `${urls.PROXIES_PREFIX}${urls.VALIDATE_ENROLLMENT}`,
|
|
6114
|
+
data: {
|
|
6115
|
+
courseId,
|
|
6116
|
+
partnerId,
|
|
6117
|
+
},
|
|
6118
|
+
};
|
|
6119
|
+
return this.http.post(option.url, option.data);
|
|
6333
6120
|
}
|
|
6334
6121
|
/**
|
|
6335
6122
|
* Submit consent for content
|
|
6336
6123
|
*/
|
|
6337
6124
|
consentSubmit(request) {
|
|
6338
|
-
return this.http.post(`${this.PROXY_SLAG_V8}/consent/v1/
|
|
6125
|
+
return this.http.post(`${this.PROXY_SLAG_V8}/consent/v1/acknowledge`, request);
|
|
6339
6126
|
}
|
|
6340
6127
|
downloadCertificate_v3(certId) {
|
|
6341
6128
|
return this.http.get(`/apis/protected/v8/cohorts/course/batch/cert/download/${certId}`);
|
|
6342
6129
|
}
|
|
6130
|
+
validateCertificate(data) {
|
|
6131
|
+
const option = {
|
|
6132
|
+
data,
|
|
6133
|
+
// url: `${urls.PROXIES_PREFIX}learner/${urls.VALIDATE_CERTIFICATE}`,
|
|
6134
|
+
url: `${urls.LEARNER_PREFIX}${urls.VALIDATE_CERTIFICATE}`,
|
|
6135
|
+
};
|
|
6136
|
+
return this.http.post(option.url, option.data);
|
|
6137
|
+
}
|
|
6138
|
+
searchCertificate(recipientId) {
|
|
6139
|
+
const option = {
|
|
6140
|
+
url: `${urls.LEARNER_PREFIX}${urls.SEARCH_CERTIFICATE}`,
|
|
6141
|
+
data: {
|
|
6142
|
+
request: {
|
|
6143
|
+
_source: ['data.badge.issuer.name', 'pdfUrl', 'data.issuedOn', 'data.badge.name'],
|
|
6144
|
+
query: {
|
|
6145
|
+
bool: {
|
|
6146
|
+
must: [{
|
|
6147
|
+
match_phrase: { 'recipient.id': recipientId },
|
|
6148
|
+
}],
|
|
6149
|
+
},
|
|
6150
|
+
},
|
|
6151
|
+
size: 50,
|
|
6152
|
+
},
|
|
6153
|
+
},
|
|
6154
|
+
};
|
|
6155
|
+
return this.http.post(option.url, option.data);
|
|
6156
|
+
}
|
|
6343
6157
|
static { this.ษตfac = i0.ษตษตngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CertificateService, deps: [{ token: i1.HttpClient }], target: i0.ษตษตFactoryTarget.Injectable }); }
|
|
6344
6158
|
static { this.ษตprov = i0.ษตษตngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CertificateService, providedIn: 'root' }); }
|
|
6345
6159
|
}
|
|
@@ -6511,18 +6325,11 @@ class AppTocContentCardV2Component {
|
|
|
6511
6325
|
// Subscribe to hashmap updates to recompute cached properties when progress changes
|
|
6512
6326
|
this.hashmapUpdatedSubscription = this.appTocSvc.hashmapUpdated$.subscribe((update) => {
|
|
6513
6327
|
if (update && update.hashmap) {
|
|
6514
|
-
console.log('๐ก [CONTENT CARD] Received hashmap update for:', this.content?.identifier, this.content?.name);
|
|
6515
6328
|
// IMPORTANT: Update hierarchyMapData with the latest hashmap from the service
|
|
6516
6329
|
// This ensures the component uses the updated data, not the stale @Input reference
|
|
6517
6330
|
this.hierarchyMapData = update.hashmap;
|
|
6518
6331
|
const prevLockState = this._cachedIsMilestoneLocked;
|
|
6519
6332
|
this.computeAllCachedProperties();
|
|
6520
|
-
console.log('๐ก [CONTENT CARD] Lock state change:', {
|
|
6521
|
-
id: this.content?.identifier,
|
|
6522
|
-
previousLockState: prevLockState,
|
|
6523
|
-
newLockState: this._cachedIsMilestoneLocked,
|
|
6524
|
-
isMilestone: this._cachedIsMilestone
|
|
6525
|
-
});
|
|
6526
6333
|
// Force Angular change detection to update the view
|
|
6527
6334
|
this.cdr.detectChanges();
|
|
6528
6335
|
}
|
|
@@ -6650,22 +6457,14 @@ class AppTocContentCardV2Component {
|
|
|
6650
6457
|
}
|
|
6651
6458
|
// Check if hashmap has pre-computed locking status (preferred - computed by service)
|
|
6652
6459
|
const hashData = this.hierarchyMapData && this.hierarchyMapData[this.content.identifier];
|
|
6653
|
-
console.log(`๐ [MILESTONE LOCK CHECK] ${this.content.identifier} (${this.content.name}):`, {
|
|
6654
|
-
hasHashData: !!hashData,
|
|
6655
|
-
computedIsLocked: hashData?.computedIsLocked,
|
|
6656
|
-
hasComputedIsLocked: hashData?.computedIsLocked !== undefined,
|
|
6657
|
-
contentIsLocked: this.content.isLocked
|
|
6658
|
-
});
|
|
6659
6460
|
// CRITICAL: Only use computedIsLocked from hashmap - this is the SINGLE SOURCE OF TRUTH
|
|
6660
6461
|
// The service computes this value based on pre-assessment/milestone completion
|
|
6661
6462
|
if (hashData && hashData.computedIsLocked !== undefined) {
|
|
6662
|
-
console.log(` โ
Using hashmap computedIsLocked: ${hashData.computedIsLocked}`);
|
|
6663
6463
|
return hashData.computedIsLocked;
|
|
6664
6464
|
}
|
|
6665
6465
|
// IMPORTANT: If no computedIsLocked value exists, default to LOCKED
|
|
6666
6466
|
// This ensures milestones stay locked until the service explicitly unlocks them
|
|
6667
6467
|
// DO NOT use this.content.isLocked as it may be false by default from API
|
|
6668
|
-
console.log(` โ ๏ธ No computedIsLocked in hashmap - defaulting to LOCKED`);
|
|
6669
6468
|
return true;
|
|
6670
6469
|
}
|
|
6671
6470
|
computeIsParentMilestoneLocked() {
|
|
@@ -6733,40 +6532,19 @@ class AppTocContentCardV2Component {
|
|
|
6733
6532
|
// or fallback to content.parent if hashmap entry doesn't exist
|
|
6734
6533
|
const contentHashData = this.hierarchyMapData[this.content.identifier];
|
|
6735
6534
|
const parentId = contentHashData?.parent || this.content.parent;
|
|
6736
|
-
console.log(`๐ computeIsMilestoneAssessment for "${this.content.name}" (${this.content.identifier}):`, {
|
|
6737
|
-
contentId: this.content.identifier,
|
|
6738
|
-
primaryCategory: this.content.primaryCategory,
|
|
6739
|
-
mimeType: this.content.mimeType,
|
|
6740
|
-
contentParent: this.content.parent,
|
|
6741
|
-
hashmapParent: contentHashData?.parent,
|
|
6742
|
-
resolvedParentId: parentId,
|
|
6743
|
-
hasParentData: !!this.hierarchyMapData[parentId]
|
|
6744
|
-
});
|
|
6745
6535
|
if (parentId && this.hierarchyMapData[parentId]) {
|
|
6746
6536
|
const parentData = this.hierarchyMapData[parentId];
|
|
6747
|
-
console.log(` Parent details:`, {
|
|
6748
|
-
parentId: parentId,
|
|
6749
|
-
parentName: parentData?.name,
|
|
6750
|
-
parentPrimaryCategory: parentData?.primaryCategory,
|
|
6751
|
-
parentIsMilestone: parentData?.isMilestone,
|
|
6752
|
-
parentCourseCategory: parentData?.courseCategory,
|
|
6753
|
-
});
|
|
6754
6537
|
// Check if DIRECT parent is a milestone - ONLY this case
|
|
6755
6538
|
const isParentMilestone = parentData.isMilestone ||
|
|
6756
6539
|
parentData.primaryCategory === 'Milestone' ||
|
|
6757
6540
|
parentData.courseCategory === 'Milestone';
|
|
6758
6541
|
if (isParentMilestone) {
|
|
6759
|
-
console.log(` โ
Result: IS a milestone assessment (direct child of milestone)`);
|
|
6760
6542
|
return true;
|
|
6761
6543
|
}
|
|
6762
|
-
console.log(` โ Result: NOT a milestone assessment (parent is ${parentData.primaryCategory}, not a Milestone)`);
|
|
6763
6544
|
// DO NOT check grandparent - course assessments inside courses within milestones
|
|
6764
6545
|
// should NOT be treated as milestone assessments
|
|
6765
6546
|
return false;
|
|
6766
6547
|
}
|
|
6767
|
-
else {
|
|
6768
|
-
console.log(` โ ๏ธ No parent data found for ${parentId}`);
|
|
6769
|
-
}
|
|
6770
6548
|
return false;
|
|
6771
6549
|
}
|
|
6772
6550
|
/**
|
|
@@ -6784,13 +6562,7 @@ class AppTocContentCardV2Component {
|
|
|
6784
6562
|
}
|
|
6785
6563
|
// Only apply to assessments that are DIRECT children of milestones
|
|
6786
6564
|
const isMilestoneAssessment = this._cachedIsMilestoneAssessment || this.computeIsMilestoneAssessment();
|
|
6787
|
-
console.log(`๐ computeIsMilestoneAssessmentLocked for "${this.content?.name}":`, {
|
|
6788
|
-
isMilestoneAssessment,
|
|
6789
|
-
_cachedIsMilestoneAssessment: this._cachedIsMilestoneAssessment,
|
|
6790
|
-
courseCategory: this.baseContentReadData?.courseCategory,
|
|
6791
|
-
});
|
|
6792
6565
|
if (!isMilestoneAssessment) {
|
|
6793
|
-
console.log(`๐ "${this.content?.name}" NOT locked - not a milestone assessment`);
|
|
6794
6566
|
return false;
|
|
6795
6567
|
}
|
|
6796
6568
|
// Check if hashmap has pre-computed assessment locking status
|
|
@@ -6912,8 +6684,6 @@ class AppTocContentCardV2Component {
|
|
|
6912
6684
|
if (shouldRecomputeCache) {
|
|
6913
6685
|
this.computeAllCachedProperties();
|
|
6914
6686
|
}
|
|
6915
|
-
// console.log('pre assessment content---', this.content)
|
|
6916
|
-
// console.log('this.hierarchyMapData---', this.hierarchyMapData)
|
|
6917
6687
|
}
|
|
6918
6688
|
check(content) {
|
|
6919
6689
|
if (this.expandActive) {
|
|
@@ -7127,7 +6897,6 @@ class AppTocContentCardV2Component {
|
|
|
7127
6897
|
// const total = localContentData.leafNodes.reduce((sum: number, childId: string) => {
|
|
7128
6898
|
// return sum + Number(this.hierarchyMapData[childId].completionPercentage || 0)
|
|
7129
6899
|
// }, 0)
|
|
7130
|
-
// console.log('total ', total)
|
|
7131
6900
|
// if(total > 0) {
|
|
7132
6901
|
// this.hierarchyMapData[identifier]['completionPercentage'] = total / _.toInteger(_.get(this.hierarchyMapData[identifier], 'leafNodesCount'))
|
|
7133
6902
|
// }
|
|
@@ -7149,8 +6918,6 @@ class AppTocContentCardV2Component {
|
|
|
7149
6918
|
return '';
|
|
7150
6919
|
}
|
|
7151
6920
|
getCompletionPercentage(identifier) {
|
|
7152
|
-
// console.log('getCompletionPercentage', identifier)
|
|
7153
|
-
// console.log('this.hierarchyMapData[identifier] : ', this.hierarchyMapData[identifier])
|
|
7154
6921
|
// const item = this.updateChildParentMap(identifier)
|
|
7155
6922
|
let percent = this.hierarchyMapData && this.hierarchyMapData[identifier] && this.hierarchyMapData[identifier].completionPercentage || 0;
|
|
7156
6923
|
return this.roundIfDecimal(percent);
|
|
@@ -7162,7 +6929,6 @@ class AppTocContentCardV2Component {
|
|
|
7162
6929
|
return value;
|
|
7163
6930
|
}
|
|
7164
6931
|
getCompletionStatus(identifier) {
|
|
7165
|
-
// console.log('getCompletionStatus')
|
|
7166
6932
|
// const item = this.updateChildParentMap(identifier)
|
|
7167
6933
|
return this.hierarchyMapData && this.hierarchyMapData[identifier] && this.hierarchyMapData[identifier].completionStatus;
|
|
7168
6934
|
}
|
|
@@ -7365,7 +7131,6 @@ class AppTocContentCardV2Component {
|
|
|
7365
7131
|
}
|
|
7366
7132
|
}
|
|
7367
7133
|
});
|
|
7368
|
-
console.log('Milestone content check:', { allMandatoryComplete, hasAssessment, assessmentComplete });
|
|
7369
7134
|
// Milestone is complete if assessment is complete (mandatory courses optional based on requirements)
|
|
7370
7135
|
return hasAssessment ? assessmentComplete : allMandatoryComplete;
|
|
7371
7136
|
}
|
|
@@ -7382,7 +7147,6 @@ class AppTocContentCardV2Component {
|
|
|
7382
7147
|
// Extract milestone number from ID (M1 -> 1, M2 -> 2, etc.)
|
|
7383
7148
|
const milestoneNum = parseInt(milestoneId.replace(/\D/g, '')) || 0;
|
|
7384
7149
|
const requiredCompletedAssessments = milestoneNum - 1; // For M2, need 1; for M3, need 2
|
|
7385
|
-
console.log(`Milestone ${milestoneId} (num: ${milestoneNum}) requires ${requiredCompletedAssessments} completed assessments`);
|
|
7386
7150
|
if (requiredCompletedAssessments <= 0) {
|
|
7387
7151
|
return true; // First milestone, no requirements
|
|
7388
7152
|
}
|
|
@@ -7400,14 +7164,9 @@ class AppTocContentCardV2Component {
|
|
|
7400
7164
|
const hasParent = item.parent && item.parent !== learningPathwayId;
|
|
7401
7165
|
if (hasParent) {
|
|
7402
7166
|
completedMilestoneAssessmentCount++;
|
|
7403
|
-
console.log(`Found completed MILESTONE assessment: ${key}`, item);
|
|
7404
|
-
}
|
|
7405
|
-
else {
|
|
7406
|
-
console.log(`Skipping root-level/pre-enrollment assessment: ${key}`);
|
|
7407
7167
|
}
|
|
7408
7168
|
}
|
|
7409
7169
|
}
|
|
7410
|
-
console.log(`Total completed MILESTONE assessments: ${completedMilestoneAssessmentCount}, Required: ${requiredCompletedAssessments}`);
|
|
7411
7170
|
// If we have enough completed milestone assessments, unlock this milestone
|
|
7412
7171
|
return completedMilestoneAssessmentCount >= requiredCompletedAssessments;
|
|
7413
7172
|
}
|
|
@@ -7553,8 +7312,6 @@ class AppTocContentCardV2Component {
|
|
|
7553
7312
|
}
|
|
7554
7313
|
const pageId = `app/toc/pageId/${content.identifier}`;
|
|
7555
7314
|
this.resourceDownloadHelperSvc.downloadPDF(content, pageId);
|
|
7556
|
-
console.log('content', content);
|
|
7557
|
-
console.log('baseContent', this.baseContentReadData);
|
|
7558
7315
|
}
|
|
7559
7316
|
/**
|
|
7560
7317
|
* View milestone achievement - calls the achievement API and shows the result
|
|
@@ -7570,7 +7327,6 @@ class AppTocContentCardV2Component {
|
|
|
7570
7327
|
// Get user ID from ConfigurationsService
|
|
7571
7328
|
const userId = this.configSvc?.userProfile?.userId;
|
|
7572
7329
|
if (!userId) {
|
|
7573
|
-
console.error('User ID not found');
|
|
7574
7330
|
return;
|
|
7575
7331
|
}
|
|
7576
7332
|
// Extract milestone ID (e.g., "m1", "m2") from the content name or index
|
|
@@ -7585,7 +7341,6 @@ class AppTocContentCardV2Component {
|
|
|
7585
7341
|
this.appTocSvc.generateMilestoneAchievement(userId, courseId, this.batchId, milestoneId).subscribe({
|
|
7586
7342
|
next: (response) => {
|
|
7587
7343
|
this.achievementLoading = false;
|
|
7588
|
-
console.log('Achievement generated successfully:', response);
|
|
7589
7344
|
// Show achievement dialog or handle response
|
|
7590
7345
|
if (response && response.result) {
|
|
7591
7346
|
// Open a dialog to show the achievement
|
|
@@ -7609,7 +7364,6 @@ class AppTocContentCardV2Component {
|
|
|
7609
7364
|
verticalPosition: 'bottom',
|
|
7610
7365
|
panelClass: ['error-snackbar']
|
|
7611
7366
|
});
|
|
7612
|
-
console.error('Error generating achievement:', error);
|
|
7613
7367
|
}
|
|
7614
7368
|
});
|
|
7615
7369
|
}
|
|
@@ -9227,13 +8981,11 @@ class ContentTocComponent {
|
|
|
9227
8981
|
}
|
|
9228
8982
|
ngOnInit() {
|
|
9229
8983
|
if (this.configService.iGOTAIConfig && this.configService.iGOTAIConfig?.aiTutor && this.configService.iGOTAIConfig?.aiTutor?.all) {
|
|
9230
|
-
// console.log('this.contentReadData--', this.route.snapshot.data)
|
|
9231
8984
|
this.enableAITutorFlag = this.onlyscormAssessmentExists(this.route.snapshot?.data?.content?.data?.children, 'mimeType', ['application/vnd.ekstep.html-archive', 'application/vnd.sunbird.questionset', 'application/json', 'text/x-url']);
|
|
9232
8985
|
// this.enableAITutorFlag = true
|
|
9233
8986
|
}
|
|
9234
8987
|
else if (this.configService.iGOTAIConfig && this.configService.iGOTAIConfig?.aiTutor && this.configService.iGOTAIConfig?.aiTutor?.forOrg && this.configService.iGOTAIConfig.aiTutor?.forOrg?.length &&
|
|
9235
8988
|
this.configService.iGOTAIConfig?.aiTutor?.forOrg.includes(this.configService.userProfile?.rootOrgId)) {
|
|
9236
|
-
// console.log('this.contentReadData--', this.route.snapshot.data)
|
|
9237
8989
|
this.enableAITutorFlag = this.onlyscormAssessmentExists(this.route.snapshot?.data?.content?.data?.children, 'mimeType', ['application/vnd.ekstep.html-archive', 'application/vnd.sunbird.questionset', 'application/json', 'text/x-url']);
|
|
9238
8990
|
// this.enableAITutorFlag = true
|
|
9239
8991
|
}
|
|
@@ -9241,22 +8993,18 @@ class ContentTocComponent {
|
|
|
9241
8993
|
this.enableAITutorFlag = false;
|
|
9242
8994
|
}
|
|
9243
8995
|
if (this.configService.iGOTAIConfig && this.configService.iGOTAIConfig?.transcription?.all) {
|
|
9244
|
-
// console.log('in')
|
|
9245
8996
|
// this.resourceIdentifier$ = this.tocSvc.transriptionIdentifier.subscribe((value:any)=>{
|
|
9246
|
-
// // console.log('resource identifier', value)
|
|
9247
8997
|
// if(value && value?.identifier) {
|
|
9248
8998
|
// this.resourceIdentifier = value?.identifier //value?.identifier // do_1138891198489067521147
|
|
9249
8999
|
// this.parseVTT()
|
|
9250
9000
|
// }
|
|
9251
9001
|
// })
|
|
9252
9002
|
this.subTitles$ = this.tocSvc.transcriptionData$.subscribe((value) => {
|
|
9253
|
-
// console.log('value', value)
|
|
9254
9003
|
this.keywordToHighlight = value;
|
|
9255
9004
|
});
|
|
9256
9005
|
this.transriptionLanguageSub = this.tocSvc.transriptionActiveLanguageDataObject$
|
|
9257
9006
|
.pipe(tap((langvalue) => console.log('tap langvalue:', langvalue)))
|
|
9258
9007
|
.subscribe((langvalue) => {
|
|
9259
|
-
// console.log('langValue', langvalue);
|
|
9260
9008
|
if (langvalue) {
|
|
9261
9009
|
// this.renderSelectedLanguageTranscription();
|
|
9262
9010
|
}
|
|
@@ -9265,22 +9013,18 @@ class ContentTocComponent {
|
|
|
9265
9013
|
}
|
|
9266
9014
|
else if (this.configService.iGOTAIConfig && this.configService.iGOTAIConfig?.transcription && this.configService.iGOTAIConfig?.transcription?.forOrg && this.configService.iGOTAIConfig?.transcription?.forOrg?.length &&
|
|
9267
9015
|
this.configService.iGOTAIConfig?.transcription?.forOrg?.includes(this.configService.userProfile?.rootOrgId)) {
|
|
9268
|
-
// console.log('in')
|
|
9269
9016
|
// this.resourceIdentifier$ = this.tocSvc.transriptionIdentifier.subscribe((value:any)=>{
|
|
9270
|
-
// // console.log('resource identifier', value)
|
|
9271
9017
|
// if(value && value?.identifier) {
|
|
9272
9018
|
// this.resourceIdentifier = value?.identifier //value?.identifier // do_1138891198489067521147
|
|
9273
9019
|
// this.parseVTT()
|
|
9274
9020
|
// }
|
|
9275
9021
|
// })
|
|
9276
9022
|
this.subTitles$ = this.tocSvc.transcriptionData$.subscribe((value) => {
|
|
9277
|
-
// console.log('value', value)
|
|
9278
9023
|
this.keywordToHighlight = value;
|
|
9279
9024
|
});
|
|
9280
9025
|
this.transriptionLanguageSub = this.tocSvc.transriptionActiveLanguageDataObject$
|
|
9281
9026
|
.pipe(tap((langvalue) => console.log('tap langvalue:', langvalue)))
|
|
9282
9027
|
.subscribe((langvalue) => {
|
|
9283
|
-
// console.log('langValue', langvalue);
|
|
9284
9028
|
if (langvalue) {
|
|
9285
9029
|
// this.renderSelectedLanguageTranscription();
|
|
9286
9030
|
}
|
|
@@ -9348,7 +9092,6 @@ class ContentTocComponent {
|
|
|
9348
9092
|
this.enableTranscriptionFlag = false;
|
|
9349
9093
|
}
|
|
9350
9094
|
if (this.configService.iGOTAIConfig && this.configService.iGOTAIConfig?.aiTutor && this.configService.iGOTAIConfig.aiTutor?.all) {
|
|
9351
|
-
// console.log('this.contentReadData--', this.route.snapshot.data)
|
|
9352
9095
|
this.enableAITutorFlag = this.onlyscormAssessmentExists(this.content?.children, 'mimeType', ['application/vnd.ekstep.html-archive', 'application/vnd.sunbird.questionset', 'application/json', 'text/x-url']);
|
|
9353
9096
|
// this.enableAITutorFlag = true
|
|
9354
9097
|
}
|
|
@@ -9375,7 +9118,6 @@ class ContentTocComponent {
|
|
|
9375
9118
|
if (this.config && this.config.discussWidgetData) {
|
|
9376
9119
|
this.discussWidgetData = this.config.discussWidgetData;
|
|
9377
9120
|
if (this.baseContentReadData && this.baseContentReadData.identifier) {
|
|
9378
|
-
// console.log('this.content.identifier', this.content.identifier)
|
|
9379
9121
|
if (!this.discussWidgetData.newCommentSection.commentTreeData.entityId) {
|
|
9380
9122
|
this.discussWidgetData.newCommentSection.commentTreeData.entityId = this.baseContentReadData.identifier;
|
|
9381
9123
|
}
|
|
@@ -9499,8 +9241,6 @@ class ContentTocComponent {
|
|
|
9499
9241
|
this.tabChangeValue = event.tab;
|
|
9500
9242
|
this.selectedTabIndex = event.index;
|
|
9501
9243
|
this.loadCheckService.componentLoaded(true);
|
|
9502
|
-
// console.log('event', event)
|
|
9503
|
-
// console.log('this.content', this.viewerDataSvc?.resourceId)
|
|
9504
9244
|
if (event && event.tab.textLabel === 'AI Tutor') {
|
|
9505
9245
|
this.showAITutorPopup = true;
|
|
9506
9246
|
}
|
|
@@ -9562,8 +9302,6 @@ class ContentTocComponent {
|
|
|
9562
9302
|
}
|
|
9563
9303
|
this.resumeDataLink = viewerRouteGenerator(resumeDataV2.identifier, resumeDataV2.mimeType, this.content.identifier, this.content.contentType, this.forPreview, 'Learning Resource', this.getBatchId(), this.content.name);
|
|
9564
9304
|
this.actionSVC.setUpdateCompGroupO = this.resumeDataLink;
|
|
9565
|
-
// console.log('this.resumeDataLink',this.resumeDataLink)
|
|
9566
|
-
// console.log('this.actionSVC', this.actionSVC)
|
|
9567
9305
|
this.router.navigate([this.resumeDataLink.url], {
|
|
9568
9306
|
queryParams: {
|
|
9569
9307
|
...this.resumeDataLink.queryParams,
|
|
@@ -9671,10 +9409,8 @@ class ContentTocComponent {
|
|
|
9671
9409
|
this.vttLangArr = data[0]['transcription_urls'];
|
|
9672
9410
|
this.enableTranscriptionFlag = true;
|
|
9673
9411
|
// let url = data[0]['transcription_urls'][0]['uri']
|
|
9674
|
-
// console.log('this.vttLangArr--',this.vttLangArr)
|
|
9675
9412
|
this.transcriptionActiveLanguage = this.vttLangArr && this.vttLangArr.length && this.vttLangArr[0] && this.vttLangArr[0]['default_lang'] ? 'en' : 'en';
|
|
9676
9413
|
this.defaultTranscriptLanguage = this.vttLangArr && this.vttLangArr.length && this.vttLangArr[0] && this.vttLangArr[0]['default_lang'] ? 'en' : 'en';
|
|
9677
|
-
// console.log('this.transcriptionActiveLanguage--', this.transcriptionActiveLanguage)
|
|
9678
9414
|
let selectedTranscriptionStyle = this.vttLangArr.filter((item) => {
|
|
9679
9415
|
return item?.label === this.transcriptionActiveLanguage;
|
|
9680
9416
|
});
|
|
@@ -9684,7 +9420,6 @@ class ContentTocComponent {
|
|
|
9684
9420
|
else {
|
|
9685
9421
|
this.selectedTranscriptionStyle = this.vttLangArr[0];
|
|
9686
9422
|
}
|
|
9687
|
-
// console.log('this.selectedTranscriptionStyle--', this.selectedTranscriptionStyle)
|
|
9688
9423
|
const filteredArr = this.vttLangArr.filter((item) => item.label === this.transcriptionActiveLanguage);
|
|
9689
9424
|
let url = filteredArr.length > 0 ? filteredArr[0].uri : null;
|
|
9690
9425
|
//let url = this.vttLangArr.filter((item: any) => item.label === this.transcriptionActiveLanguage)[0]['uri']
|
|
@@ -9693,12 +9428,6 @@ class ContentTocComponent {
|
|
|
9693
9428
|
let blocks = file.getBlocks();
|
|
9694
9429
|
this.subTitles = blocks;
|
|
9695
9430
|
}
|
|
9696
|
-
// console.log('this.vttLangArr--',this.vttLangArr)
|
|
9697
|
-
// if(this.vttLangArr && this.vttLangArr.length) {
|
|
9698
|
-
// this.transcriptionActiveLanguage = this.vttLangArr[0]['label']
|
|
9699
|
-
// } else {
|
|
9700
|
-
// this.transcriptionActiveLanguage = this.vttLangArr[0]['default_lang']
|
|
9701
|
-
// }
|
|
9702
9431
|
this.tocSvc.changeTranscriptionLanguageEvent.next({ activeLang: this.transcriptionActiveLanguage, langData: this.vttLangArr, loadPlayer: true });
|
|
9703
9432
|
}
|
|
9704
9433
|
else {
|
|
@@ -9754,8 +9483,6 @@ class ContentTocComponent {
|
|
|
9754
9483
|
onlyscormAssessmentExists(data, key, value) {
|
|
9755
9484
|
for (let i = 0; i < data?.length; i++) {
|
|
9756
9485
|
if (data[i] && data[i]['children'] && data[i]['children'].length) {
|
|
9757
|
-
// this.totalResource = this.totalResource + 1
|
|
9758
|
-
// console.log('in children')
|
|
9759
9486
|
this.onlyscormAssessmentExists(data[i]?.children, key, value);
|
|
9760
9487
|
}
|
|
9761
9488
|
else {
|
|
@@ -12444,14 +12171,9 @@ class ViewerUtilService {
|
|
|
12444
12171
|
this.http
|
|
12445
12172
|
.patch(`${this.API_ENDPOINTS.PROGRESS_UPDATE}/${contentId}`, req)
|
|
12446
12173
|
.subscribe(noop, noop);
|
|
12447
|
-
console.log(`๐ [PROGRESS UPDATE] realTimeProgressUpdate called for ${contentId}`);
|
|
12448
|
-
console.log(` Status: ${req.request.contents[0].status}, Percentage: ${req.request.contents[0].completionPercentage}`);
|
|
12449
|
-
console.log(` Hashmap has contentId: ${!!this.tocSvc.hashmap[contentId]}`);
|
|
12450
12174
|
if (this.tocSvc.hashmap[contentId]) {
|
|
12451
12175
|
const currentStatus = this.tocSvc.hashmap[contentId]['completionStatus'];
|
|
12452
|
-
console.log(` Current completionStatus in hashmap: ${currentStatus}`);
|
|
12453
12176
|
if (!currentStatus || currentStatus < 2) {
|
|
12454
|
-
console.log(` โ
Updating hashmap for ${contentId}`);
|
|
12455
12177
|
this.tocSvc.hashmap[contentId]['completionPercentage'] = req.request.contents[0].completionPercentage;
|
|
12456
12178
|
this.tocSvc.hashmap[contentId]['completionStatus'] = Number(req.request.contents[0].status) || 0;
|
|
12457
12179
|
this.tocSvc.hashmap = { ...this.tocSvc.hashmap };
|
|
@@ -12460,12 +12182,6 @@ class ViewerUtilService {
|
|
|
12460
12182
|
// Emit to trigger viewer component refresh for Learning Pathways
|
|
12461
12183
|
this.markAsCompleteSubject.next(true);
|
|
12462
12184
|
}
|
|
12463
|
-
else {
|
|
12464
|
-
console.log(` โญ๏ธ Skipping update - content already completed (status=${currentStatus})`);
|
|
12465
|
-
}
|
|
12466
|
-
}
|
|
12467
|
-
else {
|
|
12468
|
-
console.log(` โ ๏ธ ContentId ${contentId} not found in hashmap - cannot update progress`);
|
|
12469
12185
|
}
|
|
12470
12186
|
}
|
|
12471
12187
|
else {
|
|
@@ -12663,14 +12379,9 @@ class ViewerUtilService {
|
|
|
12663
12379
|
this.http
|
|
12664
12380
|
.patch(`${this.API_ENDPOINTS.PROGRESS_UPDATE}/${contentId}`, req)
|
|
12665
12381
|
.subscribe(noop, noop);
|
|
12666
|
-
console.log(`๐ [PROGRESS UPDATE QUIZ] realTimeProgressUpdateQuiz called for ${contentId}`);
|
|
12667
|
-
console.log(` Status: ${req.request.contents[0].status}, Percentage: ${req.request.contents[0].completionPercentage}`);
|
|
12668
|
-
console.log(` Hashmap exists: ${!!this.tocSvc.hashmap}, Hashmap has contentId: ${!!(this.tocSvc.hashmap && this.tocSvc.hashmap[contentId])}`);
|
|
12669
12382
|
if (this.tocSvc.hashmap && this.tocSvc.hashmap[contentId] && req.request.contents[0]) {
|
|
12670
12383
|
const currentStatus = this.tocSvc.hashmap[contentId]['completionStatus'];
|
|
12671
|
-
console.log(` Current completionStatus in hashmap: ${currentStatus}`);
|
|
12672
12384
|
if (!currentStatus || currentStatus < 2) {
|
|
12673
|
-
console.log(` โ
Updating hashmap for ${contentId}`);
|
|
12674
12385
|
this.tocSvc.hashmap[contentId]['completionPercentage'] = req.request.contents[0].completionPercentage;
|
|
12675
12386
|
this.tocSvc.hashmap[contentId]['completionStatus'] = Number(req.request.contents[0].status) || 0;
|
|
12676
12387
|
this.tocSvc.hashmap = { ...this.tocSvc.hashmap };
|
|
@@ -12681,12 +12392,6 @@ class ViewerUtilService {
|
|
|
12681
12392
|
// Emit to trigger viewer component refresh for Learning Pathways
|
|
12682
12393
|
this.markAsCompleteSubject.next(true);
|
|
12683
12394
|
}
|
|
12684
|
-
else {
|
|
12685
|
-
console.log(` โญ๏ธ Skipping update - content already completed (status=${currentStatus})`);
|
|
12686
|
-
}
|
|
12687
|
-
}
|
|
12688
|
-
else {
|
|
12689
|
-
console.log(` โ ๏ธ Cannot update hashmap - hashmap or contentId missing`);
|
|
12690
12395
|
}
|
|
12691
12396
|
}
|
|
12692
12397
|
else {
|
|
@@ -12750,15 +12455,6 @@ class ViewerUtilService {
|
|
|
12750
12455
|
return this.http.get(`/apis/proxies/v8/action/content/v3/hierarchy/${id}?mode=${type}`);
|
|
12751
12456
|
}
|
|
12752
12457
|
updateContentHashMapForAssesstent(contentId, contentProgress) {
|
|
12753
|
-
console.log('๐ [UPDATE HASHMAP] Updating assessment in hashmap:', {
|
|
12754
|
-
contentId,
|
|
12755
|
-
incomingProgress: contentProgress,
|
|
12756
|
-
currentHashmapData: this.tocSvc.hashmap[contentId] ? {
|
|
12757
|
-
completionPercentage: this.tocSvc.hashmap[contentId]['completionPercentage'],
|
|
12758
|
-
completionStatus: this.tocSvc.hashmap[contentId]['completionStatus'],
|
|
12759
|
-
status: this.tocSvc.hashmap[contentId]['status']
|
|
12760
|
-
} : 'not found'
|
|
12761
|
-
});
|
|
12762
12458
|
if (this.tocSvc.hashmap[contentId]) {
|
|
12763
12459
|
const currentStatus = this.tocSvc.hashmap[contentId]['completionStatus'] || 0;
|
|
12764
12460
|
const newStatus = Number(contentProgress.status) || 0;
|
|
@@ -12767,29 +12463,15 @@ class ViewerUtilService {
|
|
|
12767
12463
|
this.tocSvc.hashmap[contentId]['completionPercentage'] = contentProgress.completionPercentage;
|
|
12768
12464
|
this.tocSvc.hashmap[contentId]['completionStatus'] = newStatus;
|
|
12769
12465
|
this.tocSvc.hashmap[contentId]['status'] = newStatus;
|
|
12770
|
-
console.log('โ
[UPDATE HASHMAP] Updated assessment:', {
|
|
12771
|
-
contentId,
|
|
12772
|
-
name: this.tocSvc.hashmap[contentId]['name'],
|
|
12773
|
-
completionPercentage: contentProgress.completionPercentage,
|
|
12774
|
-
completionStatus: newStatus,
|
|
12775
|
-
status: newStatus
|
|
12776
|
-
});
|
|
12777
12466
|
// Create new hashmap reference for Angular change detection
|
|
12778
12467
|
this.tocSvc.hashmap = { ...this.tocSvc.hashmap };
|
|
12779
12468
|
// Trigger milestone lock recomputation - it will emit hashmapUpdated with both progress and lock changes
|
|
12780
12469
|
if (this.tocSvc.triggerMilestoneLockUpdate) {
|
|
12781
|
-
console.log('๐ [UPDATE HASHMAP] Triggering milestone lock update after assessment update');
|
|
12782
12470
|
this.tocSvc.triggerMilestoneLockUpdate();
|
|
12783
12471
|
}
|
|
12784
12472
|
// Emit to trigger viewer component refresh for Learning Pathways
|
|
12785
12473
|
this.markAsCompleteSubject.next(true);
|
|
12786
12474
|
}
|
|
12787
|
-
else {
|
|
12788
|
-
console.log('โน๏ธ [UPDATE HASHMAP] Skipping update - already complete or lower status');
|
|
12789
|
-
}
|
|
12790
|
-
}
|
|
12791
|
-
else {
|
|
12792
|
-
console.log('โ ๏ธ [UPDATE HASHMAP] Content not found in hashmap:', contentId);
|
|
12793
12475
|
}
|
|
12794
12476
|
}
|
|
12795
12477
|
getFormById(formId) {
|
|
@@ -12870,8 +12552,6 @@ class ViewerUtilService {
|
|
|
12870
12552
|
// Emit to trigger viewer component refresh for Learning Pathways
|
|
12871
12553
|
this.markAsCompleteSubject.next(true);
|
|
12872
12554
|
}
|
|
12873
|
-
// console.log('Updated hashmap:', this.tocSvc.hashmap)
|
|
12874
|
-
// console.log('this.tocSvc.hashmap---', this.tocSvc.hashmap)
|
|
12875
12555
|
}
|
|
12876
12556
|
else {
|
|
12877
12557
|
req = {};
|
|
@@ -12905,13 +12585,10 @@ class ViewerUtilService {
|
|
|
12905
12585
|
.patch(`${this.API_ENDPOINTS.PRE_ASSESSMENT_STATE_UPDATE}`, req)
|
|
12906
12586
|
.subscribe(noop, noop);
|
|
12907
12587
|
}
|
|
12908
|
-
console.log('๐ฏ [PRE-ASSESSMENT QUIZ] Updating progress for:', contentId);
|
|
12909
|
-
console.log(' Status:', status, 'Completion:', req.request.contents[0].completionPercentage);
|
|
12910
12588
|
// Update hashmap - create entry if it doesn't exist
|
|
12911
12589
|
if (this.tocSvc.hashmap) {
|
|
12912
12590
|
if (!this.tocSvc.hashmap[contentId]) {
|
|
12913
12591
|
// Create new entry for pre-assessment if it doesn't exist
|
|
12914
|
-
console.log(' Creating new hashmap entry for pre-assessment');
|
|
12915
12592
|
this.tocSvc.hashmap[contentId] = {
|
|
12916
12593
|
identifier: contentId,
|
|
12917
12594
|
completionPercentage: req.request.contents[0].completionPercentage,
|
|
@@ -12922,16 +12599,13 @@ class ViewerUtilService {
|
|
|
12922
12599
|
}
|
|
12923
12600
|
else {
|
|
12924
12601
|
// Update existing entry
|
|
12925
|
-
console.log(' Updating existing hashmap entry');
|
|
12926
12602
|
this.tocSvc.hashmap[contentId]['completionPercentage'] = req.request.contents[0].completionPercentage;
|
|
12927
12603
|
this.tocSvc.hashmap[contentId]['completionStatus'] = Number(req.request.contents[0].status) || 0;
|
|
12928
12604
|
this.tocSvc.hashmap[contentId]['status'] = Number(req.request.contents[0].status) || 0;
|
|
12929
12605
|
}
|
|
12930
|
-
console.log(' Hashmap entry after update:', this.tocSvc.hashmap[contentId]);
|
|
12931
12606
|
this.tocSvc.hashmap = { ...this.tocSvc.hashmap };
|
|
12932
12607
|
// ALWAYS trigger milestone lock recomputation when pre-assessment completes
|
|
12933
12608
|
// This ensures milestone 1 unlocks immediately after pre-assessment completion
|
|
12934
|
-
console.log('๐ [PRE-ASSESSMENT QUIZ] Triggering milestone lock update');
|
|
12935
12609
|
if (this.tocSvc.triggerMilestoneLockUpdate) {
|
|
12936
12610
|
this.tocSvc.triggerMilestoneLockUpdate();
|
|
12937
12611
|
}
|
|
@@ -15878,19 +15552,9 @@ class AppTocV2Service {
|
|
|
15878
15552
|
contentHeirarchy['preliminaryAssessmentDetail'].parent = contentHeirarchy.identifier;
|
|
15879
15553
|
// Mark this as the pre-assessment for milestone locking logic
|
|
15880
15554
|
contentHeirarchy['preliminaryAssessmentDetail'].isPreAssessment = true;
|
|
15881
|
-
console.log('๐ [CONSTRUCT HIERARCHY] Setting isPreAssessment=true on preliminaryAssessmentDetail:', {
|
|
15882
|
-
id: contentHeirarchy['preliminaryAssessmentDetail'].identifier,
|
|
15883
|
-
name: contentHeirarchy['preliminaryAssessmentDetail'].name,
|
|
15884
|
-
isPreAssessment: contentHeirarchy['preliminaryAssessmentDetail'].isPreAssessment,
|
|
15885
|
-
parent: contentHeirarchy['preliminaryAssessmentDetail'].parent,
|
|
15886
|
-
primaryCategory: contentHeirarchy['preliminaryAssessmentDetail'].primaryCategory
|
|
15887
|
-
});
|
|
15888
15555
|
contentHeirarchy['children'].push(contentHeirarchy['preliminaryAssessmentDetail']);
|
|
15889
15556
|
leafNodes.push(contentReadData?.preliminaryAssessment || contentReadData?.preliminaryAssessmentDetail?.identifier);
|
|
15890
15557
|
}
|
|
15891
|
-
else {
|
|
15892
|
-
console.log('โ ๏ธ [CONSTRUCT HIERARCHY] No preliminaryAssessmentDetail found in contentReadData');
|
|
15893
|
-
}
|
|
15894
15558
|
// Track milestone index for proper locking logic
|
|
15895
15559
|
// All milestones are locked by default - unlocking is computed based on progress
|
|
15896
15560
|
let milestoneIndex = 0;
|
|
@@ -16078,15 +15742,6 @@ class AppTocV2Service {
|
|
|
16078
15742
|
node.completionPercentage = progress;
|
|
16079
15743
|
node.completionStatus = status;
|
|
16080
15744
|
node.status = status;
|
|
16081
|
-
console.log(`Direct enrollment found for ${node.identifier}:`, {
|
|
16082
|
-
completionPercentage: progress,
|
|
16083
|
-
completionStatus: status,
|
|
16084
|
-
enrollmentData: {
|
|
16085
|
-
progress: enrollment.progress,
|
|
16086
|
-
completionPercentage: enrollment.completionPercentage,
|
|
16087
|
-
status: enrollment.status
|
|
16088
|
-
}
|
|
16089
|
-
});
|
|
16090
15745
|
return;
|
|
16091
15746
|
}
|
|
16092
15747
|
// Try both contentId and collectionId as the API response may use either field
|
|
@@ -16118,11 +15773,6 @@ class AppTocV2Service {
|
|
|
16118
15773
|
node.completionStatus = 0;
|
|
16119
15774
|
node.status = 0;
|
|
16120
15775
|
}
|
|
16121
|
-
console.log(`Updated node progress for ${node.identifier}:`, {
|
|
16122
|
-
completionStatus: node.completionStatus,
|
|
16123
|
-
completionPercentage: node.completionPercentage,
|
|
16124
|
-
status: node.status
|
|
16125
|
-
});
|
|
16126
15776
|
}
|
|
16127
15777
|
updateCourseProgress(course, parentContentIdentifier, enrollmentListData) {
|
|
16128
15778
|
const enrollment = this.findEnrollment(enrollmentListData, course?.identifier);
|
|
@@ -21635,7 +21285,6 @@ class AppTocHomeV2Component {
|
|
|
21635
21285
|
// CRITICAL: For Learning Pathways, compute milestone locking status after enrollment
|
|
21636
21286
|
// This ensures milestones are properly locked until pre-assessment is completed
|
|
21637
21287
|
if (this.baseContentReadData?.courseCategory === 'Learning Pathway') {
|
|
21638
|
-
console.log('๐ [ENROLLMENT] Computing milestone locking for Learning Pathway after enrollment');
|
|
21639
21288
|
this.tocSvc.callHirarchyProgressHashmap(this.content);
|
|
21640
21289
|
this.tocSvc.computeMilestoneLockingStatus(true);
|
|
21641
21290
|
this.syncMilestoneLockStatus();
|
|
@@ -22172,10 +21821,8 @@ class AppTocHomeV2Component {
|
|
|
22172
21821
|
// Recompute milestone locking status from existing hashmap
|
|
22173
21822
|
// The hashmap is already updated with latest progress via hashmap update subscription
|
|
22174
21823
|
this.tocSvc.computeMilestoneLockingStatus(isEnrolled);
|
|
22175
|
-
console.log('๐ Milestone locking recomputed from hashmap. Enrolled:', isEnrolled);
|
|
22176
21824
|
// Sync lock status from hashmap to content tree
|
|
22177
21825
|
this.syncMilestoneLockStatus();
|
|
22178
|
-
console.log('โ
Milestone locks refreshed from hashmap');
|
|
22179
21826
|
}
|
|
22180
21827
|
catch (error) {
|
|
22181
21828
|
console.error('โ Error in refreshEnrollmentAndProgress:', error);
|