@learnpack/learnpack 5.0.298 → 5.0.300

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 (79) hide show
  1. package/README.md +409 -409
  2. package/lib/commands/audit.js +15 -15
  3. package/lib/commands/breakToken.js +19 -19
  4. package/lib/commands/clean.js +3 -3
  5. package/lib/commands/logout.js +3 -3
  6. package/lib/commands/serve.js +31 -11
  7. package/lib/creatorDist/assets/{index-D25zkBaN.js → index-DoYRptnk.js} +11875 -11992
  8. package/lib/creatorDist/index.html +1 -1
  9. package/lib/managers/config/index.js +77 -77
  10. package/lib/utils/creatorUtilities.js +14 -14
  11. package/lib/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  12. package/lib/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
  13. package/lib/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -110
  14. package/lib/utils/templates/scorm/config/index.html +209 -209
  15. package/lib/utils/templates/scorm/ims_xml.xsd +1 -1
  16. package/lib/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
  17. package/lib/utils/templates/scorm/imsmanifest.xml +38 -38
  18. package/lib/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
  19. package/package.json +1 -1
  20. package/src/commands/audit.ts +487 -487
  21. package/src/commands/breakToken.ts +67 -67
  22. package/src/commands/clean.ts +30 -30
  23. package/src/commands/logout.ts +38 -38
  24. package/src/commands/serve.ts +47 -25
  25. package/src/commands/start.ts +333 -333
  26. package/src/commands/translate.ts +123 -123
  27. package/src/creator/README.md +54 -54
  28. package/src/creator/package-lock.json +6621 -6621
  29. package/src/creator/package.json +55 -55
  30. package/src/creator/src/App.tsx +569 -569
  31. package/src/creator/src/components/FileUploader.tsx +302 -302
  32. package/src/creator/src/components/Icon.tsx +18 -18
  33. package/src/creator/src/components/LessonItem.tsx +152 -152
  34. package/src/creator/src/components/Login.tsx +259 -259
  35. package/src/creator/src/components/syllabus/ContentIndex.tsx +323 -323
  36. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +337 -337
  37. package/src/creator/src/i18n.ts +28 -28
  38. package/src/creator/src/locales/en.json +127 -127
  39. package/src/creator/src/locales/es.json +127 -127
  40. package/src/creator/src/utils/configTypes.ts +122 -122
  41. package/src/creator/src/utils/constants.ts +13 -13
  42. package/src/creator/src/utils/creatorUtils.ts +46 -46
  43. package/src/creator/src/utils/eventBus.ts +2 -2
  44. package/src/creator/src/utils/socket.ts +61 -61
  45. package/src/creator/src/utils/store.ts +222 -222
  46. package/src/creator/src/vite-env.d.ts +1 -1
  47. package/src/creator/vite.config.ts +13 -13
  48. package/src/creatorDist/assets/{index-D25zkBaN.js → index-DoYRptnk.js} +11875 -11992
  49. package/src/creatorDist/index.html +1 -1
  50. package/src/managers/config/defaults.ts +49 -49
  51. package/src/managers/config/exercise.ts +364 -364
  52. package/src/managers/config/index.ts +775 -775
  53. package/src/managers/file.ts +236 -236
  54. package/src/managers/server/routes.ts +554 -554
  55. package/src/managers/telemetry.ts +188 -188
  56. package/src/models/action.ts +13 -13
  57. package/src/models/config-manager.ts +28 -28
  58. package/src/models/config.ts +106 -106
  59. package/src/models/exercise-obj.ts +30 -30
  60. package/src/models/session.ts +39 -39
  61. package/src/models/socket.ts +61 -61
  62. package/src/models/status.ts +16 -16
  63. package/src/utils/BaseCommand.ts +56 -56
  64. package/src/utils/audit.ts +392 -392
  65. package/src/utils/checkNotInstalled.ts +267 -267
  66. package/src/utils/convertCreds.js +34 -34
  67. package/src/utils/creatorUtilities.ts +504 -504
  68. package/src/utils/export/README.md +178 -178
  69. package/src/utils/incrementVersion.js +74 -74
  70. package/src/utils/misc.ts +58 -58
  71. package/src/utils/sidebarGenerator.ts +195 -195
  72. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  73. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
  74. package/src/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -110
  75. package/src/utils/templates/scorm/config/index.html +209 -209
  76. package/src/utils/templates/scorm/ims_xml.xsd +1 -1
  77. package/src/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
  78. package/src/utils/templates/scorm/imsmanifest.xml +38 -38
  79. package/src/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
@@ -1,152 +1,152 @@
1
- // import { useState, useRef } from "react"
2
- // import { SVGS } from "../assets/svgs"
3
-
4
- import { useState } from "react"
5
- import { useRef } from "react"
6
- import { SVGS } from "../assets/svgs"
7
- import useStore from "../utils/store"
8
- import { Icon } from "./Icon"
9
-
10
- export interface Lesson {
11
- id: string
12
- uid: string
13
- title: string
14
- type: "READ" | "CODE" | "QUIZ"
15
- description: string
16
- duration?: number
17
- locked?: boolean
18
- }
19
-
20
- const typeToEmoji: Record<string, string> = {
21
- read: "📖",
22
- code: "💻",
23
- quiz: "🧠",
24
- }
25
-
26
- interface LessonItemProps {
27
- lesson: Lesson
28
- isNew: boolean
29
- onChange: (uid: string, newTitle: string) => void
30
- onRemove: () => void
31
- onToggleLock?: (uid: string) => void
32
- }
33
-
34
- function cleanFloatString(input: string): string {
35
- const num = parseFloat(input)
36
- const isInteger = Number.isInteger(num)
37
-
38
- return isInteger
39
- ? Math.floor(num).toString().padStart(2, "0")
40
- : num.toString()
41
- }
42
-
43
- function hasDecimalPart(input: string): boolean {
44
- const num = parseFloat(input)
45
- if (Number.isNaN(num)) return false
46
- return num % 1 > 0
47
- }
48
-
49
- export const LessonItem: React.FC<LessonItemProps> = ({
50
- lesson,
51
- onChange,
52
- onRemove,
53
- onToggleLock,
54
- isNew,
55
- }) => {
56
- const mode = useStore((state) => state.mode)
57
- const inputRef = useRef<HTMLInputElement>(null)
58
- const [isEditing, setIsEditing] = useState(false)
59
-
60
- return (
61
- <div
62
- className={`flex items-center space-x-2 relative rounded-md p-3 ${
63
- isNew ? "border border-learnpack-blue appear" : "border border-gray-200"
64
- } ${hasDecimalPart(lesson.id.toString() || "0") ? "ml-6" : ""}`}
65
- >
66
- {isNew && <span className="yellow-ball"></span>}
67
-
68
- {mode === "teacher" && (
69
- <>
70
- <span className="index-circle">{cleanFloatString(lesson.id)}</span>
71
- </>
72
- )}
73
-
74
- <span className="text-gray-500 text-sm">
75
- {typeToEmoji[lesson.type.toLowerCase()]}
76
- </span>
77
- {isEditing ? (
78
- <input
79
- defaultValue={lesson.title}
80
- ref={inputRef}
81
- onBlur={() => {
82
- if (inputRef.current) {
83
- onChange(lesson.uid, inputRef.current.value)
84
- }
85
- }}
86
- autoFocus
87
- className="flex-1 bg-white border border-gray-300 rounded-md px-2 py-1 text-sm"
88
- />
89
- ) : (
90
- <span className="flex-1 text-sm text-gray-800">{lesson.title}</span>
91
- )}
92
-
93
- <span className="text-sm text-gray-600 bg-blue-100 px-2 py-1 rounded-full">
94
- {lesson.duration} min
95
- </span>
96
-
97
- {mode === "teacher" && (
98
- <>
99
- <button
100
- onClick={() => onToggleLock?.(lesson.uid)}
101
- className={`cursor-pointer ${
102
- lesson.locked
103
- ? "text-yellow-600 hover:text-yellow-700"
104
- : "text-gray-400 hover:text-yellow-600"
105
- }`}
106
- title={lesson.locked ? "Unlock lesson" : "Lock lesson"}
107
- >
108
- <Icon
109
- name={lesson.locked ? "Lock" : "Unlock"}
110
- size={16}
111
- />
112
- </button>
113
- <button
114
- onClick={() => {
115
- if (!lesson.locked) {
116
- setIsEditing(!isEditing)
117
- if (inputRef.current) {
118
- onChange(lesson.uid, inputRef.current.value)
119
- }
120
- }
121
- }}
122
- className={`${
123
- lesson.locked
124
- ? "text-gray-300 cursor-not-allowed"
125
- : "text-gray-500 hover:text-blue-500 cursor-pointer"
126
- }`}
127
- disabled={lesson.locked}
128
- title={lesson.locked ? "Cannot edit locked lesson" : "Edit lesson"}
129
- >
130
- <Icon name="Edit" size={16} />
131
- </button>
132
- <button
133
- onClick={() => {
134
- if (!lesson.locked) {
135
- onRemove()
136
- }
137
- }}
138
- className={`${
139
- lesson.locked
140
- ? "text-gray-300 cursor-not-allowed"
141
- : "text-red-500 hover:text-red-700 cursor-pointer"
142
- }`}
143
- disabled={lesson.locked}
144
- title={lesson.locked ? "Cannot delete locked lesson" : "Delete lesson"}
145
- >
146
- {SVGS.trash}
147
- </button>
148
- </>
149
- )}
150
- </div>
151
- )
152
- }
1
+ // import { useState, useRef } from "react"
2
+ // import { SVGS } from "../assets/svgs"
3
+
4
+ import { useState } from "react"
5
+ import { useRef } from "react"
6
+ import { SVGS } from "../assets/svgs"
7
+ import useStore from "../utils/store"
8
+ import { Icon } from "./Icon"
9
+
10
+ export interface Lesson {
11
+ id: string
12
+ uid: string
13
+ title: string
14
+ type: "READ" | "CODE" | "QUIZ"
15
+ description: string
16
+ duration?: number
17
+ locked?: boolean
18
+ }
19
+
20
+ const typeToEmoji: Record<string, string> = {
21
+ read: "📖",
22
+ code: "💻",
23
+ quiz: "🧠",
24
+ }
25
+
26
+ interface LessonItemProps {
27
+ lesson: Lesson
28
+ isNew: boolean
29
+ onChange: (uid: string, newTitle: string) => void
30
+ onRemove: () => void
31
+ onToggleLock?: (uid: string) => void
32
+ }
33
+
34
+ function cleanFloatString(input: string): string {
35
+ const num = parseFloat(input)
36
+ const isInteger = Number.isInteger(num)
37
+
38
+ return isInteger
39
+ ? Math.floor(num).toString().padStart(2, "0")
40
+ : num.toString()
41
+ }
42
+
43
+ function hasDecimalPart(input: string): boolean {
44
+ const num = parseFloat(input)
45
+ if (Number.isNaN(num)) return false
46
+ return num % 1 > 0
47
+ }
48
+
49
+ export const LessonItem: React.FC<LessonItemProps> = ({
50
+ lesson,
51
+ onChange,
52
+ onRemove,
53
+ onToggleLock,
54
+ isNew,
55
+ }) => {
56
+ const mode = useStore((state) => state.mode)
57
+ const inputRef = useRef<HTMLInputElement>(null)
58
+ const [isEditing, setIsEditing] = useState(false)
59
+
60
+ return (
61
+ <div
62
+ className={`flex items-center space-x-2 relative rounded-md p-3 ${
63
+ isNew ? "border border-learnpack-blue appear" : "border border-gray-200"
64
+ } ${hasDecimalPart(lesson.id.toString() || "0") ? "ml-6" : ""}`}
65
+ >
66
+ {isNew && <span className="yellow-ball"></span>}
67
+
68
+ {mode === "teacher" && (
69
+ <>
70
+ <span className="index-circle">{cleanFloatString(lesson.id)}</span>
71
+ </>
72
+ )}
73
+
74
+ <span className="text-gray-500 text-sm">
75
+ {typeToEmoji[lesson.type.toLowerCase()]}
76
+ </span>
77
+ {isEditing ? (
78
+ <input
79
+ defaultValue={lesson.title}
80
+ ref={inputRef}
81
+ onBlur={() => {
82
+ if (inputRef.current) {
83
+ onChange(lesson.uid, inputRef.current.value)
84
+ }
85
+ }}
86
+ autoFocus
87
+ className="flex-1 bg-white border border-gray-300 rounded-md px-2 py-1 text-sm"
88
+ />
89
+ ) : (
90
+ <span className="flex-1 text-sm text-gray-800">{lesson.title}</span>
91
+ )}
92
+
93
+ <span className="text-sm text-gray-600 bg-blue-100 px-2 py-1 rounded-full">
94
+ {lesson.duration} min
95
+ </span>
96
+
97
+ {mode === "teacher" && (
98
+ <>
99
+ <button
100
+ onClick={() => onToggleLock?.(lesson.uid)}
101
+ className={`cursor-pointer ${
102
+ lesson.locked
103
+ ? "text-yellow-600 hover:text-yellow-700"
104
+ : "text-gray-400 hover:text-yellow-600"
105
+ }`}
106
+ title={lesson.locked ? "Unlock lesson" : "Lock lesson"}
107
+ >
108
+ <Icon
109
+ name={lesson.locked ? "Lock" : "Unlock"}
110
+ size={16}
111
+ />
112
+ </button>
113
+ <button
114
+ onClick={() => {
115
+ if (!lesson.locked) {
116
+ setIsEditing(!isEditing)
117
+ if (inputRef.current) {
118
+ onChange(lesson.uid, inputRef.current.value)
119
+ }
120
+ }
121
+ }}
122
+ className={`${
123
+ lesson.locked
124
+ ? "text-gray-300 cursor-not-allowed"
125
+ : "text-gray-500 hover:text-blue-500 cursor-pointer"
126
+ }`}
127
+ disabled={lesson.locked}
128
+ title={lesson.locked ? "Cannot edit locked lesson" : "Edit lesson"}
129
+ >
130
+ <Icon name="Edit" size={16} />
131
+ </button>
132
+ <button
133
+ onClick={() => {
134
+ if (!lesson.locked) {
135
+ onRemove()
136
+ }
137
+ }}
138
+ className={`${
139
+ lesson.locked
140
+ ? "text-gray-300 cursor-not-allowed"
141
+ : "text-red-500 hover:text-red-700 cursor-pointer"
142
+ }`}
143
+ disabled={lesson.locked}
144
+ title={lesson.locked ? "Cannot delete locked lesson" : "Delete lesson"}
145
+ >
146
+ {SVGS.trash}
147
+ </button>
148
+ </>
149
+ )}
150
+ </div>
151
+ )
152
+ }