@learnpack/learnpack 5.0.361 → 5.0.363

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.
Files changed (41) hide show
  1. package/lib/commands/serve.js +44 -7
  2. package/lib/creatorDist/assets/{index-B7s5Nmq8.css → index-Cco3XhDR.css} +96 -0
  3. package/lib/creatorDist/assets/{index-CqVEKiJR.js → index-o3Cw0bsF.js} +69682 -66808
  4. package/lib/creatorDist/index.html +2 -2
  5. package/lib/utils/api.d.ts +0 -9
  6. package/lib/utils/api.js +1 -65
  7. package/lib/utils/lessonRecovery.d.ts +18 -0
  8. package/lib/utils/lessonRecovery.js +31 -0
  9. package/package.json +1 -1
  10. package/src/commands/serve.ts +65 -18
  11. package/src/creator/package-lock.json +297 -3
  12. package/src/creator/package.json +1 -0
  13. package/src/creator/src/App.test.tsx +124 -1
  14. package/src/creator/src/App.tsx +52 -36
  15. package/src/creator/src/components/FileCard.tsx +63 -19
  16. package/src/creator/src/components/FileReadListener.test.tsx +128 -0
  17. package/src/creator/src/components/FileReadListener.tsx +75 -0
  18. package/src/creator/src/components/FileReviewModal.test.tsx +193 -0
  19. package/src/creator/src/components/FileReviewModal.tsx +128 -0
  20. package/src/creator/src/components/FileUploader.test.tsx +229 -0
  21. package/src/creator/src/components/FileUploader.tsx +212 -58
  22. package/src/creator/src/components/GenerationErrorCard.tsx +57 -0
  23. package/src/creator/src/components/MarkdownRenderer.tsx +4 -2
  24. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +6 -9
  25. package/src/creator/src/index.css +45 -0
  26. package/src/creator/src/locales/en.json +27 -5
  27. package/src/creator/src/locales/es.json +27 -5
  28. package/src/creator/src/main.tsx +2 -0
  29. package/src/creator/src/utils/completionResult.test.ts +61 -0
  30. package/src/creator/src/utils/completionResult.ts +61 -2
  31. package/src/creator/src/utils/courseLanguage.test.ts +6 -0
  32. package/src/creator/src/utils/creationRequest.test.ts +53 -18
  33. package/src/creator/src/utils/creationRequest.ts +17 -12
  34. package/src/creator/src/utils/fileRead.ts +60 -0
  35. package/src/creator/src/utils/lib.ts +0 -5
  36. package/src/creator/src/utils/store.ts +0 -10
  37. package/src/creatorDist/assets/{index-B7s5Nmq8.css → index-Cco3XhDR.css} +96 -0
  38. package/src/creatorDist/assets/{index-CqVEKiJR.js → index-o3Cw0bsF.js} +69682 -66808
  39. package/src/creatorDist/index.html +2 -2
  40. package/src/utils/api.ts +0 -83
  41. package/src/utils/lessonRecovery.ts +32 -0
@@ -23,6 +23,7 @@ const rigoActions_1 = require("../utils/rigoActions");
23
23
  const dotenv = require("dotenv");
24
24
  // import { v4 as uuidv4 } from "uuid"
25
25
  const creatorUtilities_1 = require("../utils/creatorUtilities");
26
+ const lessonRecovery_1 = require("../utils/lessonRecovery");
26
27
  // import { handleAssetCreation } from "./publish"
27
28
  const axios_1 = require("axios");
28
29
  const FormData = require("form-data");
@@ -407,6 +408,9 @@ async function startInitialContentGeneration(rigoToken, steps, packageContext, e
407
408
  };
408
409
  const res = await (0, rigoActions_1.initialContentGenerator)(rigoToken.trim(), inputs, webhookUrl, endpointSlug);
409
410
  console.log("INITIAL CONTENT GENERATOR RES", res);
411
+ if (!res) {
412
+ throw new Error(`Could not start generating lesson ${exSlug}`);
413
+ }
410
414
  return res.id;
411
415
  }
412
416
  async function startInteractivityGeneration(rigoToken, steps, packageContext, exercise, courseSlug, purposeSlug, bucket, lastLesson = "") {
@@ -620,6 +624,32 @@ async function updateLessonStatusToDone(courseSlug, exerciseSlug, bucket) {
620
624
  throw error;
621
625
  }
622
626
  }
627
+ const lessonSlug = (lesson) => (0, creatorUtilities_2.slugify)(lesson.id + "-" + lesson.title);
628
+ async function repairFinishedLessons(courseSlug, syllabus, bucket) {
629
+ var _a;
630
+ const language = syllabus.courseInfo.language || "en";
631
+ try {
632
+ const finished = await (0, lessonRecovery_1.findFinishedLessons)((_a = syllabus.lessons) !== null && _a !== void 0 ? _a : [], async (lesson) => {
633
+ const readme = bucket.file(`courses/${courseSlug}/exercises/${lessonSlug(lesson)}/README${(0, creatorUtilities_1.getReadmeExtension)(language)}`);
634
+ const [exists] = await readme.exists();
635
+ if (!exists)
636
+ return null;
637
+ const [content] = await readme.download();
638
+ return content.toString();
639
+ });
640
+ for (const lesson of finished) {
641
+ // eslint-disable-next-line no-await-in-loop
642
+ await updateLessonStatusToDone(courseSlug, lessonSlug(lesson), bucket);
643
+ lesson.status = "DONE";
644
+ lesson.generated = true;
645
+ }
646
+ }
647
+ catch (error) {
648
+ // Loading the course matters more than repairing it now. The next load
649
+ // tries again.
650
+ console.error(`Error repairing lessons of ${courseSlug}:`, error);
651
+ }
652
+ }
623
653
  async function continueWithNextLesson(courseSlug, currentExerciseIndex, rigoToken, finalContent, bucket) {
624
654
  const syllabus = await getSyllabus(courseSlug, bucket);
625
655
  const nextExercise = syllabus.lessons[currentExerciseIndex + 1] || null;
@@ -633,7 +663,19 @@ async function continueWithNextLesson(courseSlug, currentExerciseIndex, rigoToke
633
663
  if (syllabus.feedback) {
634
664
  feedback = `\n\nThe user added the following feedback with relation to the previous generations: ${syllabus.feedback}`;
635
665
  }
636
- nextCompletionId = await startInitialContentGeneration(rigoToken, syllabus.lessons, syllabus.courseInfo, nextExercise, courseSlug, syllabus.courseInfo.purpose, finalContent + "\n\n" + feedback);
666
+ try {
667
+ nextCompletionId = await startInitialContentGeneration(rigoToken, syllabus.lessons, syllabus.courseInfo, nextExercise, courseSlug, syllabus.courseInfo.purpose, finalContent + "\n\n" + feedback);
668
+ }
669
+ catch (error) {
670
+ // The current lesson is finished either way. The next one stays PENDING,
671
+ // and its screen offers to continue.
672
+ console.error("Error starting the next lesson:", error);
673
+ (0, creatorSocket_1.emitToCourse)(courseSlug, "course-creation", {
674
+ lesson: (0, creatorUtilities_2.slugify)(nextExercise.id + "-" + nextExercise.title),
675
+ status: "error",
676
+ log: `❌ Could not start lesson ${nextExercise.title}`,
677
+ });
678
+ }
637
679
  }
638
680
  else {
639
681
  console.log("Stopping generation process at", currentExerciseIndex, syllabus.lessons[currentExerciseIndex].title, "because it's a multiple of 3");
@@ -952,7 +994,6 @@ class ServeCommand extends SessionCommand_1.default {
952
994
  if (!crendsEnv) {
953
995
  process.exit(1);
954
996
  }
955
- await api_1.default.updateTechnologiesPeriodically();
956
997
  const credentials = JSON.parse(crendsEnv);
957
998
  const bucketStorage = new storage_1.Storage({
958
999
  credentials,
@@ -3498,11 +3539,6 @@ class ServeCommand extends SessionCommand_1.default {
3498
3539
  res.status(500).json({ error: error.message });
3499
3540
  }
3500
3541
  });
3501
- app.get("/technologies", async (req, res) => {
3502
- console.log("GET /technologies");
3503
- const technologies = await api_1.default.getCurrentTechnologies();
3504
- res.json(technologies);
3505
- });
3506
3542
  app.get("/assets/:file", (req, res) => {
3507
3543
  const file = path.join(localAppPath, req.params.file);
3508
3544
  res.sendFile(file);
@@ -3591,6 +3627,7 @@ class ServeCommand extends SessionCommand_1.default {
3591
3627
  const [content] = await syllabus.download();
3592
3628
  const syllabusJson = JSON.parse(content.toString());
3593
3629
  sanitizeSyllabusFromUnknown(syllabusJson);
3630
+ await repairFinishedLessons(courseSlug, syllabusJson, bucket);
3594
3631
  res.json(syllabusJson);
3595
3632
  }
3596
3633
  catch (error) {
@@ -57,9 +57,14 @@
57
57
  "Liberation Mono", "Courier New", monospace;
58
58
  --color-red-50: oklch(97.1% 0.013 17.38);
59
59
  --color-red-100: oklch(93.6% 0.032 17.717);
60
+ --color-red-300: oklch(80.8% 0.114 19.571);
60
61
  --color-red-500: oklch(63.7% 0.237 25.331);
61
62
  --color-red-600: oklch(57.7% 0.245 27.325);
62
63
  --color-red-700: oklch(50.5% 0.213 27.518);
64
+ --color-amber-50: oklch(98.7% 0.022 95.277);
65
+ --color-amber-100: oklch(96.2% 0.059 95.617);
66
+ --color-amber-300: oklch(87.9% 0.169 91.605);
67
+ --color-amber-800: oklch(47.3% 0.137 46.201);
63
68
  --color-yellow-600: oklch(68.1% 0.162 75.834);
64
69
  --color-yellow-700: oklch(55.4% 0.135 66.442);
65
70
  --color-blue-50: oklch(97% 0.014 254.604);
@@ -89,6 +94,7 @@
89
94
  --container-sm: 24rem;
90
95
  --container-md: 28rem;
91
96
  --container-xl: 36rem;
97
+ --container-3xl: 48rem;
92
98
  --text-xs: 0.75rem;
93
99
  --text-xs--line-height: calc(1 / 0.75);
94
100
  --text-sm: 0.875rem;
@@ -540,6 +546,9 @@
540
546
  .ml-auto {
541
547
  margin-left: auto;
542
548
  }
549
+ .block {
550
+ display: block;
551
+ }
543
552
  .flex {
544
553
  display: flex;
545
554
  }
@@ -564,6 +573,9 @@
564
573
  .h-2 {
565
574
  height: calc(var(--spacing) * 2);
566
575
  }
576
+ .h-3 {
577
+ height: calc(var(--spacing) * 3);
578
+ }
567
579
  .h-4 {
568
580
  height: calc(var(--spacing) * 4);
569
581
  }
@@ -609,9 +621,15 @@
609
621
  .max-h-\[78vh\] {
610
622
  max-height: 78vh;
611
623
  }
624
+ .max-h-\[90vh\] {
625
+ max-height: 90vh;
626
+ }
612
627
  .max-h-\[300px\] {
613
628
  max-height: 300px;
614
629
  }
630
+ .min-h-48 {
631
+ min-height: calc(var(--spacing) * 48);
632
+ }
615
633
  .min-h-\[69vh\] {
616
634
  min-height: 69vh;
617
635
  }
@@ -621,6 +639,9 @@
621
639
  .w-2 {
622
640
  width: calc(var(--spacing) * 2);
623
641
  }
642
+ .w-3 {
643
+ width: calc(var(--spacing) * 3);
644
+ }
624
645
  .w-4 {
625
646
  width: calc(var(--spacing) * 4);
626
647
  }
@@ -657,12 +678,18 @@
657
678
  .w-full {
658
679
  width: 100%;
659
680
  }
681
+ .max-w-3xl {
682
+ max-width: var(--container-3xl);
683
+ }
660
684
  .max-w-64 {
661
685
  max-width: calc(var(--spacing) * 64);
662
686
  }
663
687
  .max-w-\[700px\] {
664
688
  max-width: 700px;
665
689
  }
690
+ .max-w-full {
691
+ max-width: 100%;
692
+ }
666
693
  .max-w-md {
667
694
  max-width: var(--container-md);
668
695
  }
@@ -681,6 +708,9 @@
681
708
  .flex-1 {
682
709
  flex: 1;
683
710
  }
711
+ .shrink-0 {
712
+ flex-shrink: 0;
713
+ }
684
714
  .flex-grow {
685
715
  flex-grow: 1;
686
716
  }
@@ -852,6 +882,9 @@
852
882
  border-right-style: var(--tw-border-style);
853
883
  border-right-width: 1px;
854
884
  }
885
+ .border-amber-300 {
886
+ border-color: var(--color-amber-300);
887
+ }
855
888
  .border-blue-200 {
856
889
  border-color: var(--color-blue-200);
857
890
  }
@@ -867,12 +900,21 @@
867
900
  .border-gray-300 {
868
901
  border-color: var(--color-gray-300);
869
902
  }
903
+ .border-red-300 {
904
+ border-color: var(--color-red-300);
905
+ }
870
906
  .border-transparent {
871
907
  border-color: #0000;
872
908
  }
873
909
  .border-t-transparent {
874
910
  border-top-color: #0000;
875
911
  }
912
+ .bg-amber-50 {
913
+ background-color: var(--color-amber-50);
914
+ }
915
+ .bg-amber-100 {
916
+ background-color: var(--color-amber-100);
917
+ }
876
918
  .bg-black\/50 {
877
919
  background-color: #00000080;
878
920
  }
@@ -1027,6 +1069,9 @@
1027
1069
  .text-left {
1028
1070
  text-align: left;
1029
1071
  }
1072
+ .font-mono {
1073
+ font-family: var(--font-mono);
1074
+ }
1030
1075
  .font-sans {
1031
1076
  font-family: var(--font-sans);
1032
1077
  }
@@ -1083,6 +1128,12 @@
1083
1128
  .whitespace-pre-line {
1084
1129
  white-space: pre-line;
1085
1130
  }
1131
+ .whitespace-pre-wrap {
1132
+ white-space: pre-wrap;
1133
+ }
1134
+ .text-amber-800 {
1135
+ color: var(--color-amber-800);
1136
+ }
1086
1137
  .text-black {
1087
1138
  color: var(--color-black);
1088
1139
  }
@@ -1125,6 +1176,9 @@
1125
1176
  .text-red-600 {
1126
1177
  color: var(--color-red-600);
1127
1178
  }
1179
+ .text-red-700 {
1180
+ color: var(--color-red-700);
1181
+ }
1128
1182
  .text-white {
1129
1183
  color: var(--color-white);
1130
1184
  }
@@ -1262,6 +1316,9 @@
1262
1316
  .hover\:text-yellow-700:hover {
1263
1317
  color: var(--color-yellow-700);
1264
1318
  }
1319
+ .hover\:underline:hover {
1320
+ text-decoration-line: underline;
1321
+ }
1265
1322
  .hover\:shadow-lg:hover {
1266
1323
  --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, #0000001a),
1267
1324
  0 4px 6px -4px var(--tw-shadow-color, #0000001a);
@@ -1322,6 +1379,9 @@
1322
1379
  .sm\:flex-row {
1323
1380
  flex-direction: row;
1324
1381
  }
1382
+ .sm\:justify-center {
1383
+ justify-content: center;
1384
+ }
1325
1385
  :where(.sm\:space-y-0 > :not(:last-child)) {
1326
1386
  --tw-space-y-reverse: 0;
1327
1387
  margin-block-start: calc(
@@ -1514,6 +1574,42 @@ body {
1514
1574
  list-style-type: decimal;
1515
1575
  list-style-position: inside;
1516
1576
  }
1577
+ .markdown-renderer table {
1578
+ border-collapse: collapse;
1579
+ width: 100%;
1580
+ margin: 0.5rem 0;
1581
+ }
1582
+ .markdown-renderer th,
1583
+ .markdown-renderer td {
1584
+ text-align: left;
1585
+ vertical-align: top;
1586
+ border: 1px solid #d1d5db;
1587
+ padding: 0.25rem 0.5rem;
1588
+ }
1589
+ .markdown-renderer th {
1590
+ background-color: #f3f4f6;
1591
+ font-weight: 600;
1592
+ }
1593
+ .file-read h1,
1594
+ .file-read h2,
1595
+ .file-read h3 {
1596
+ margin-top: 0.75rem;
1597
+ font-size: 1.05rem;
1598
+ font-weight: 600;
1599
+ }
1600
+ .file-read h4 {
1601
+ color: #6b7280;
1602
+ border-bottom: 1px solid #e5e7eb;
1603
+ margin: 1rem 0 0.5rem;
1604
+ padding-bottom: 0.25rem;
1605
+ font-size: 0.75rem;
1606
+ }
1607
+ .file-read h4:first-child {
1608
+ margin-top: 0;
1609
+ }
1610
+ .file-read p {
1611
+ margin-bottom: 0.5rem;
1612
+ }
1517
1613
  .appear {
1518
1614
  transform-origin: top;
1519
1615
  opacity: 0;