@learnpack/learnpack 5.0.306 → 5.0.307
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/lib/creatorDist/assets/{index-CTQfJYti.js → index-B37w_ZhT.js} +9248 -9158
- package/lib/creatorDist/assets/{index-DTjdV1LF.css → index-D4SYZg0r.css} +3 -0
- package/lib/creatorDist/index.html +2 -2
- package/package.json +1 -1
- package/src/creator/src/App.tsx +49 -10
- package/src/creator/src/components/LanguageDetectionModal.tsx +46 -0
- package/src/creator/src/components/ParamsChecker.tsx +11 -3
- package/src/creator/src/locales/en.json +11 -0
- package/src/creator/src/locales/es.json +11 -0
- package/src/creator/src/utils/lib.ts +172 -171
- package/src/creatorDist/assets/{index-CTQfJYti.js → index-B37w_ZhT.js} +9248 -9158
- package/src/creatorDist/assets/{index-DTjdV1LF.css → index-D4SYZg0r.css} +3 -0
- package/src/creatorDist/index.html +2 -2
- package/src/ui/_app/app.js +262 -251
- package/src/ui/app.tar.gz +0 -0
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
/>
|
|
11
11
|
|
|
12
12
|
<title>Learnpack Creator: Craft tutorials in seconds!</title>
|
|
13
|
-
<script type="module" crossorigin src="/creator/assets/index-
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/creator/assets/index-
|
|
13
|
+
<script type="module" crossorigin src="/creator/assets/index-B37w_ZhT.js"></script>
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/creator/assets/index-D4SYZg0r.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@learnpack/learnpack",
|
|
3
3
|
"description": "Seamlessly build, sell and/or take interactive & auto-graded tutorials, start learning now or build a new tutorial to your audience.",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.307",
|
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
|
6
6
|
"contributors": [
|
|
7
7
|
{
|
package/src/creator/src/App.tsx
CHANGED
|
@@ -31,6 +31,7 @@ import NotificationListener from "./components/NotificationListener"
|
|
|
31
31
|
import { slugify } from "./utils/creatorUtils"
|
|
32
32
|
import TurnstileModal from "./components/TurnstileModal"
|
|
33
33
|
import { TMessage } from "./components/Message"
|
|
34
|
+
import LanguageDetectionModal from "./components/LanguageDetectionModal"
|
|
34
35
|
|
|
35
36
|
function App() {
|
|
36
37
|
const navigate = useNavigate()
|
|
@@ -72,6 +73,8 @@ function App() {
|
|
|
72
73
|
|
|
73
74
|
const [notificationId, setNotificationId] = useState<string>("")
|
|
74
75
|
const [showTurnstileModal, setShowTurnstileModal] = useState(false)
|
|
76
|
+
const [showLanguageDetectionModal, setShowLanguageDetectionModal] = useState(false)
|
|
77
|
+
const [detectedLanguage, setDetectedLanguage] = useState<string>("")
|
|
75
78
|
|
|
76
79
|
useEffect(() => {
|
|
77
80
|
if (formState.isCompleted) {
|
|
@@ -130,27 +133,45 @@ function App() {
|
|
|
130
133
|
if (duration && !isNaN(parseInt(duration))) {
|
|
131
134
|
if (["15", "30", "60"].includes(duration)) {
|
|
132
135
|
const durationInt = parseInt(duration)
|
|
133
|
-
console.log("duration", durationInt)
|
|
134
136
|
setFormState({
|
|
135
137
|
duration: durationInt,
|
|
136
138
|
})
|
|
137
139
|
} else {
|
|
138
|
-
console.
|
|
140
|
+
console.error("Invalid duration received in params", duration)
|
|
139
141
|
}
|
|
140
142
|
}
|
|
141
|
-
|
|
143
|
+
|
|
142
144
|
if (plan) {
|
|
143
145
|
setPlanToRedirect(plan)
|
|
144
146
|
} else {
|
|
145
147
|
console.debug("No plan received in params")
|
|
146
148
|
}
|
|
149
|
+
|
|
150
|
+
// Language detection logic
|
|
151
|
+
let finalLanguage = language
|
|
147
152
|
|
|
148
|
-
|
|
153
|
+
// Change if query param is provided
|
|
154
|
+
if (finalLanguage && finalLanguage.length === 2) {
|
|
155
|
+
console.log("LANGUAGE", finalLanguage)
|
|
149
156
|
setFormState({
|
|
150
|
-
language:
|
|
157
|
+
language: finalLanguage,
|
|
151
158
|
})
|
|
159
|
+
if (i18n.language !== finalLanguage) {
|
|
160
|
+
i18n.changeLanguage(finalLanguage)
|
|
161
|
+
}
|
|
152
162
|
}
|
|
153
163
|
|
|
164
|
+
// If no language is provided, detect the language of the description
|
|
165
|
+
if (!finalLanguage && description) {
|
|
166
|
+
const detectedLang = detectLanguage(description)
|
|
167
|
+
if (detectedLang && detectedLang !== i18n.language) {
|
|
168
|
+
finalLanguage = detectedLang
|
|
169
|
+
setDetectedLanguage(detectedLang)
|
|
170
|
+
setShowLanguageDetectionModal(true)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
154
175
|
if (purpose && purpose.length > 0 && possiblePurposes.includes(purpose)) {
|
|
155
176
|
setFormState({
|
|
156
177
|
purpose: purpose,
|
|
@@ -233,8 +254,6 @@ function App() {
|
|
|
233
254
|
formState.purpose || "learnpack-lesson-writer",
|
|
234
255
|
tokenType === "rigo" ? false : true
|
|
235
256
|
)
|
|
236
|
-
console.log("RES", res)
|
|
237
|
-
|
|
238
257
|
setNotificationId(res.notificationId)
|
|
239
258
|
} catch (error) {
|
|
240
259
|
console.error(error, "ERROR CREATING TUTORIAL")
|
|
@@ -254,6 +273,18 @@ function App() {
|
|
|
254
273
|
}
|
|
255
274
|
}
|
|
256
275
|
|
|
276
|
+
const handleLanguageSwitch = () => {
|
|
277
|
+
setFormState({
|
|
278
|
+
language: detectedLanguage,
|
|
279
|
+
})
|
|
280
|
+
i18n.changeLanguage(detectedLanguage)
|
|
281
|
+
setShowLanguageDetectionModal(false)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const handleLanguageStay = () => {
|
|
285
|
+
setShowLanguageDetectionModal(false)
|
|
286
|
+
}
|
|
287
|
+
|
|
257
288
|
const buildSteps = () => {
|
|
258
289
|
const steps = [
|
|
259
290
|
{
|
|
@@ -263,9 +294,11 @@ function App() {
|
|
|
263
294
|
required: true,
|
|
264
295
|
validator: (value: string) => {
|
|
265
296
|
const lang = detectLanguage(value)
|
|
297
|
+
console.log("Description validator language detection:", { lang, currentLang: i18n.language, value })
|
|
266
298
|
|
|
267
|
-
if (lang) {
|
|
268
|
-
|
|
299
|
+
if (lang && lang !== "en" && lang !== i18n.language) {
|
|
300
|
+
setDetectedLanguage(lang)
|
|
301
|
+
setShowLanguageDetectionModal(true)
|
|
269
302
|
}
|
|
270
303
|
|
|
271
304
|
return value.length > 0
|
|
@@ -451,6 +484,13 @@ function App() {
|
|
|
451
484
|
return (
|
|
452
485
|
<>
|
|
453
486
|
<ParamsChecker />
|
|
487
|
+
{showLanguageDetectionModal && (
|
|
488
|
+
<LanguageDetectionModal
|
|
489
|
+
detectedLanguage={detectedLanguage}
|
|
490
|
+
onSwitch={handleLanguageSwitch}
|
|
491
|
+
onStay={handleLanguageStay}
|
|
492
|
+
/>
|
|
493
|
+
)}
|
|
454
494
|
{showTurnstileModal && (
|
|
455
495
|
<TurnstileModal
|
|
456
496
|
onClose={() => {
|
|
@@ -477,7 +517,6 @@ function App() {
|
|
|
477
517
|
{notificationId && (
|
|
478
518
|
<NotificationListener
|
|
479
519
|
onNotification={(res) => {
|
|
480
|
-
console.log("Async response", res)
|
|
481
520
|
const lessons = res.parsed.listOfSteps.map((lesson: any) => {
|
|
482
521
|
return parseLesson(lesson, [])
|
|
483
522
|
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useTranslation } from "react-i18next"
|
|
2
|
+
|
|
3
|
+
interface LanguageDetectionModalProps {
|
|
4
|
+
detectedLanguage: string
|
|
5
|
+
onSwitch: () => void
|
|
6
|
+
onStay: () => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function LanguageDetectionModal({
|
|
10
|
+
detectedLanguage,
|
|
11
|
+
onSwitch,
|
|
12
|
+
onStay,
|
|
13
|
+
}: LanguageDetectionModalProps) {
|
|
14
|
+
const { t, i18n } = useTranslation()
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-1000">
|
|
18
|
+
<div className="bg-white p-6 rounded-xl shadow-md max-w-md w-full mx-4">
|
|
19
|
+
<h2 className="text-xl font-semibold text-center mb-4">
|
|
20
|
+
{t("languageDetection.title")}
|
|
21
|
+
</h2>
|
|
22
|
+
<p className="text-gray-600 text-center mb-6">
|
|
23
|
+
{t("languageDetection.message", {
|
|
24
|
+
language: t(`languageDetection.languages.${detectedLanguage.toLowerCase()}`)
|
|
25
|
+
})}
|
|
26
|
+
</p>
|
|
27
|
+
<div className="flex flex-col sm:flex-row gap-3">
|
|
28
|
+
<button
|
|
29
|
+
onClick={onSwitch}
|
|
30
|
+
className="flex-1 bg-blue-600 text-white py-2 px-4 rounded-md font-semibold hover:bg-blue-700 transition-colors"
|
|
31
|
+
>
|
|
32
|
+
{t("languageDetection.switchTo", {
|
|
33
|
+
language: t(`languageDetection.languages.${detectedLanguage.toLowerCase()}`)
|
|
34
|
+
})}
|
|
35
|
+
</button>
|
|
36
|
+
<button
|
|
37
|
+
onClick={onStay}
|
|
38
|
+
className="flex-1 bg-gray-200 text-gray-800 py-2 px-4 rounded-md font-semibold hover:bg-gray-300 transition-colors"
|
|
39
|
+
>
|
|
40
|
+
{t(`languageDetection.stayIn${i18n.language.toLowerCase()}`)}
|
|
41
|
+
</button>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
import { useEffect } from "react"
|
|
2
2
|
import useStore from "../utils/store"
|
|
3
|
+
import { checkParams } from "../utils/lib"
|
|
4
|
+
import { useTranslation } from "react-i18next"
|
|
3
5
|
|
|
4
6
|
export const ParamsChecker = () => {
|
|
7
|
+
const { i18n } = useTranslation()
|
|
5
8
|
const setMode = useStore((state) => state.setMode)
|
|
6
9
|
|
|
7
10
|
useEffect(() => {
|
|
8
|
-
const params =
|
|
9
|
-
const mode = params.
|
|
11
|
+
const params = checkParams(["mode", "language"])
|
|
12
|
+
const mode = params.mode
|
|
10
13
|
if (mode && ["teacher", "student"].includes(mode.toLowerCase())) {
|
|
11
|
-
console.log("Setting mode to ", mode.toLowerCase())
|
|
12
14
|
setMode(mode.toLowerCase() as "teacher" | "student")
|
|
13
15
|
}
|
|
16
|
+
if (
|
|
17
|
+
params.language &&
|
|
18
|
+
["en", "es"].includes(params.language.toLowerCase())
|
|
19
|
+
) {
|
|
20
|
+
i18n.changeLanguage(params.language.toLowerCase())
|
|
21
|
+
}
|
|
14
22
|
}, [])
|
|
15
23
|
|
|
16
24
|
return <></>
|
|
@@ -94,6 +94,17 @@
|
|
|
94
94
|
"okMessage": "If you're satisfied, type 'OK' in the chat.",
|
|
95
95
|
"instructionsMessage": "If not, what would you like me to change? You can say things like:\n - Add more exercises\n - Make it more difficult\n - Remove step 1.1 and replace it with a new step that explains the concept of X "
|
|
96
96
|
},
|
|
97
|
+
"languageDetection": {
|
|
98
|
+
"title": "Language detected",
|
|
99
|
+
"message": "We have detected {{language}} as the main language for this package, would you like to switch to {{language}}?",
|
|
100
|
+
"switchTo": "Yes, switch to {{language}}",
|
|
101
|
+
"stayInen": "Stay in English",
|
|
102
|
+
"stayInes": "Stay in Spanish",
|
|
103
|
+
"languages": {
|
|
104
|
+
"en": "English",
|
|
105
|
+
"es": "Spanish"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
97
108
|
"login": {
|
|
98
109
|
"creatingAccount": "Creating account…",
|
|
99
110
|
"loggedInSuccessfully": "Logged in successfully",
|
|
@@ -94,6 +94,17 @@
|
|
|
94
94
|
"okMessage": "Si estás satisfecho, escribe 'OK' en el chat.",
|
|
95
95
|
"instructionsMessage": "Si no, ¿qué te gustaría que cambiara? Puedes decir cosas como:\n - Añadir más ejercicios\n - Hacerlo más difícil\n - Eliminar el paso 1.1 y reemplazarlo con un nuevo paso que explique el concepto de X "
|
|
96
96
|
},
|
|
97
|
+
"languageDetection": {
|
|
98
|
+
"title": "Idioma detectado",
|
|
99
|
+
"message": "Hemos detectado {{language}} como el idioma principal para este paquete, ¿te gustaría cambiar a {{language}}?",
|
|
100
|
+
"switchTo": "Sí, cambiar a {{language}}",
|
|
101
|
+
"stayInen": "Mantenerse en Inglés",
|
|
102
|
+
"stayInes": "Mantenerse en Español",
|
|
103
|
+
"languages": {
|
|
104
|
+
"en": "Inglés",
|
|
105
|
+
"es": "Español"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
97
108
|
"login": {
|
|
98
109
|
"creatingAccount": "Creando cuenta…",
|
|
99
110
|
"loggedInSuccessfully": "Inicio de sesión exitoso",
|