@learnpack/learnpack 5.0.309 → 5.0.311

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 (88) 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/publish.js +16 -6
  7. package/lib/commands/serve.js +16 -16
  8. package/lib/creatorDist/assets/{index-B37w_ZhT.js → index-BI7U47zy.js} +13186 -13013
  9. package/lib/creatorDist/index.html +1 -1
  10. package/lib/managers/config/index.js +77 -77
  11. package/lib/utils/creatorUtilities.js +14 -14
  12. package/lib/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  13. package/lib/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
  14. package/lib/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -110
  15. package/lib/utils/templates/scorm/config/index.html +209 -209
  16. package/lib/utils/templates/scorm/ims_xml.xsd +1 -1
  17. package/lib/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
  18. package/lib/utils/templates/scorm/imsmanifest.xml +38 -38
  19. package/lib/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
  20. package/package.json +1 -1
  21. package/src/commands/audit.ts +487 -487
  22. package/src/commands/breakToken.ts +67 -67
  23. package/src/commands/clean.ts +30 -30
  24. package/src/commands/logout.ts +38 -38
  25. package/src/commands/publish.ts +39 -23
  26. package/src/commands/serve.ts +3179 -3179
  27. package/src/commands/start.ts +333 -333
  28. package/src/commands/translate.ts +123 -123
  29. package/src/creator/README.md +54 -54
  30. package/src/creator/package-lock.json +6621 -6621
  31. package/src/creator/package.json +55 -55
  32. package/src/creator/src/App.tsx +611 -608
  33. package/src/creator/src/components/FileUploader.tsx +340 -302
  34. package/src/creator/src/components/Icon.tsx +18 -18
  35. package/src/creator/src/components/LessonItem.tsx +152 -152
  36. package/src/creator/src/components/Login.tsx +259 -259
  37. package/src/creator/src/components/ParamsChecker.tsx +25 -25
  38. package/src/creator/src/components/Uploader.tsx +3 -6
  39. package/src/creator/src/components/syllabus/ContentIndex.tsx +323 -323
  40. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +341 -337
  41. package/src/creator/src/i18n.ts +28 -28
  42. package/src/creator/src/locales/en.json +139 -138
  43. package/src/creator/src/locales/es.json +139 -138
  44. package/src/creator/src/utils/configTypes.ts +122 -122
  45. package/src/creator/src/utils/constants.ts +13 -13
  46. package/src/creator/src/utils/creatorUtils.ts +46 -46
  47. package/src/creator/src/utils/eventBus.ts +2 -2
  48. package/src/creator/src/utils/rigo.ts +1 -1
  49. package/src/creator/src/utils/socket.ts +61 -61
  50. package/src/creator/src/utils/store.ts +222 -222
  51. package/src/creator/src/vite-env.d.ts +1 -1
  52. package/src/creator/vite.config.ts +13 -13
  53. package/src/creatorDist/assets/{index-B37w_ZhT.js → index-BI7U47zy.js} +13186 -13013
  54. package/src/creatorDist/index.html +1 -1
  55. package/src/managers/config/defaults.ts +49 -49
  56. package/src/managers/config/exercise.ts +364 -364
  57. package/src/managers/config/index.ts +775 -775
  58. package/src/managers/file.ts +236 -236
  59. package/src/managers/server/routes.ts +554 -554
  60. package/src/managers/telemetry.ts +188 -188
  61. package/src/models/action.ts +13 -13
  62. package/src/models/config-manager.ts +28 -28
  63. package/src/models/config.ts +106 -106
  64. package/src/models/exercise-obj.ts +30 -30
  65. package/src/models/session.ts +39 -39
  66. package/src/models/socket.ts +61 -61
  67. package/src/models/status.ts +16 -16
  68. package/src/ui/_app/app.css +1 -1
  69. package/src/ui/_app/app.js +477 -407
  70. package/src/ui/app.tar.gz +0 -0
  71. package/src/utils/BaseCommand.ts +56 -56
  72. package/src/utils/api.ts +665 -665
  73. package/src/utils/audit.ts +392 -392
  74. package/src/utils/checkNotInstalled.ts +267 -267
  75. package/src/utils/convertCreds.js +34 -34
  76. package/src/utils/creatorUtilities.ts +504 -504
  77. package/src/utils/export/README.md +178 -178
  78. package/src/utils/incrementVersion.js +74 -74
  79. package/src/utils/misc.ts +58 -58
  80. package/src/utils/sidebarGenerator.ts +195 -195
  81. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  82. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
  83. package/src/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -110
  84. package/src/utils/templates/scorm/config/index.html +209 -209
  85. package/src/utils/templates/scorm/ims_xml.xsd +1 -1
  86. package/src/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -345
  87. package/src/utils/templates/scorm/imsmanifest.xml +38 -38
  88. package/src/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -573
@@ -1,18 +1,18 @@
1
- import * as LucideIcons from "lucide-react";
2
- import { LucideProps } from "lucide-react";
3
-
4
- export interface IconProps extends Omit<LucideProps, 'ref'> {
5
- name: keyof typeof LucideIcons;
6
- }
7
-
8
- export const Icon = ({ name, ...props }: IconProps) => {
9
- const LucideIcon = LucideIcons[name] as React.ComponentType<LucideProps>;
10
-
11
- if (!LucideIcon) {
12
- console.warn(`Icon "${name}" not found in lucide-react`);
13
- return null;
14
- }
15
-
16
- return <LucideIcon {...props} />;
17
- };
18
-
1
+ import * as LucideIcons from "lucide-react";
2
+ import { LucideProps } from "lucide-react";
3
+
4
+ export interface IconProps extends Omit<LucideProps, 'ref'> {
5
+ name: keyof typeof LucideIcons;
6
+ }
7
+
8
+ export const Icon = ({ name, ...props }: IconProps) => {
9
+ const LucideIcon = LucideIcons[name] as React.ComponentType<LucideProps>;
10
+
11
+ if (!LucideIcon) {
12
+ console.warn(`Icon "${name}" not found in lucide-react`);
13
+ return null;
14
+ }
15
+
16
+ return <LucideIcon {...props} />;
17
+ };
18
+
@@ -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
+ }