@learnpack/learnpack 5.0.213 → 5.0.217
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/README.md +13 -13
- package/lib/commands/serve.d.ts +1 -1
- package/lib/commands/serve.js +79 -52
- package/lib/creatorDist/assets/{index-DxwqeFD3.js → index-CZrxF_55.js} +2807 -2763
- package/lib/creatorDist/assets/{index-Bnq3eZ3T.css → index-DmpsXknz.css} +6 -0
- package/lib/creatorDist/index.html +2 -2
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/src/commands/serve.ts +99 -62
- package/src/creator/src/components/FileUploader.tsx +35 -3
- package/src/creator/src/locales/en.json +8 -3
- package/src/creator/src/locales/es.json +7 -2
- package/src/creator/src/utils/constants.ts +2 -1
- package/src/creator/src/utils/lib.ts +9 -1
- package/src/creatorDist/assets/{index-DxwqeFD3.js → index-CZrxF_55.js} +2807 -2763
- package/src/creatorDist/assets/{index-Bnq3eZ3T.css → index-DmpsXknz.css} +6 -0
- package/src/creatorDist/index.html +2 -2
- package/src/ui/_app/app.css +1 -1
- package/src/ui/_app/app.js +326 -326
- package/src/ui/app.tar.gz +0 -0
@@ -518,6 +518,9 @@
|
|
518
518
|
.mb-6 {
|
519
519
|
margin-bottom: calc(var(--spacing) * 6);
|
520
520
|
}
|
521
|
+
.ml-2 {
|
522
|
+
margin-left: calc(var(--spacing) * 2);
|
523
|
+
}
|
521
524
|
.ml-6 {
|
522
525
|
margin-left: calc(var(--spacing) * 6);
|
523
526
|
}
|
@@ -1022,6 +1025,9 @@
|
|
1022
1025
|
.whitespace-pre-line {
|
1023
1026
|
white-space: pre-line;
|
1024
1027
|
}
|
1028
|
+
.text-black {
|
1029
|
+
color: var(--color-black);
|
1030
|
+
}
|
1025
1031
|
.text-blue-400 {
|
1026
1032
|
color: var(--color-blue-400);
|
1027
1033
|
}
|
@@ -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-CZrxF_55.js"></script>
|
14
|
+
<link rel="stylesheet" crossorigin href="/creator/assets/index-DmpsXknz.css">
|
15
15
|
</head>
|
16
16
|
<body>
|
17
17
|
<div id="root"></div>
|
package/oclif.manifest.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":"5.0.
|
1
|
+
{"version":"5.0.217","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false}},"args":[]},"breakToken":{"id":"breakToken","description":"Break the token","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Builds the project by copying necessary files and directories into a zip file","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"serve":{"id":"serve","description":"Runs a small server to build tutorials","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]},"translate":{"id":"translate","description":"List all the lessons, the user is able of select many of them to translate to the given languages","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[]}}}
|
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.217",
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
6
6
|
"contributors": [
|
7
7
|
{
|
package/src/commands/serve.ts
CHANGED
@@ -74,18 +74,18 @@ export const createLearnJson = (courseInfo: FormState) => {
|
|
74
74
|
const learnJson = {
|
75
75
|
slug: slugify(courseInfo.title as string),
|
76
76
|
title:
|
77
|
-
language === "en" ?
|
77
|
+
language === "en" || language === "us" ?
|
78
78
|
{
|
79
79
|
us: courseInfo.title,
|
80
80
|
} :
|
81
81
|
{
|
82
82
|
[language]: courseInfo.title,
|
83
|
-
// us: courseInfo.title,
|
84
83
|
},
|
85
84
|
technologies: courseInfo.technologies || [],
|
86
85
|
difficulty: "beginner",
|
87
86
|
description: {
|
88
|
-
us:
|
87
|
+
[language === "en" || language === "us" ? "us" : language]:
|
88
|
+
courseInfo.description,
|
89
89
|
},
|
90
90
|
grading: "isolated",
|
91
91
|
telemetry: {
|
@@ -453,7 +453,7 @@ export default class ServeCommand extends SessionCommand {
|
|
453
453
|
|
454
454
|
// Servir archivos estáticos
|
455
455
|
// app.use(express.static(distPath))
|
456
|
-
app.use(express.json())
|
456
|
+
app.use(express.json({ limit: "20mb" }))
|
457
457
|
app.use(cors())
|
458
458
|
|
459
459
|
const appPath = path.resolve(__dirname, "../ui/_app")
|
@@ -509,44 +509,6 @@ export default class ServeCommand extends SessionCommand {
|
|
509
509
|
stream.end(buffer)
|
510
510
|
})
|
511
511
|
|
512
|
-
app.post(
|
513
|
-
"/upload-image",
|
514
|
-
express.json({ limit: "10mb" }),
|
515
|
-
async (req, res) => {
|
516
|
-
const { image_url, destination } = req.body
|
517
|
-
if (!image_url || !destination) {
|
518
|
-
return res
|
519
|
-
.status(400)
|
520
|
-
.json({ error: "image_url and destination are required" })
|
521
|
-
}
|
522
|
-
|
523
|
-
try {
|
524
|
-
const response = await fetch(image_url)
|
525
|
-
if (!response.ok) {
|
526
|
-
return res.status(400).json({
|
527
|
-
error: `Failed to download image: ${response.statusText}`,
|
528
|
-
})
|
529
|
-
}
|
530
|
-
|
531
|
-
const contentType =
|
532
|
-
response.headers.get("content-type") || "application/octet-stream"
|
533
|
-
const buffer = await response.arrayBuffer()
|
534
|
-
|
535
|
-
const file = bucket.file(destination)
|
536
|
-
await file.save(Buffer.from(buffer), {
|
537
|
-
resumable: false,
|
538
|
-
contentType,
|
539
|
-
})
|
540
|
-
|
541
|
-
console.log(`✅ Image uploaded to ${file.name}`)
|
542
|
-
res.json({ message: "Image uploaded successfully", path: file.name })
|
543
|
-
} catch (error) {
|
544
|
-
console.error("❌ upload-image error:", error)
|
545
|
-
res.status(500).json({ error: (error as Error).message })
|
546
|
-
}
|
547
|
-
}
|
548
|
-
)
|
549
|
-
|
550
512
|
const upload = createUploadMiddleware()
|
551
513
|
|
552
514
|
app.post("/upload-image-file", upload.single("file"), async (req, res) => {
|
@@ -641,6 +603,41 @@ export default class ServeCommand extends SessionCommand {
|
|
641
603
|
res.json({ id, status: "SUCCESS" })
|
642
604
|
})
|
643
605
|
|
606
|
+
app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
|
607
|
+
const { courseSlug, imageId } = req.params
|
608
|
+
const body = req.body
|
609
|
+
console.log("RECEIVING IMAGE WEBHOOK", body)
|
610
|
+
|
611
|
+
const imageUrl = body.image_url
|
612
|
+
const imagePath = `courses/${courseSlug}/.learn/assets/${imageId}`
|
613
|
+
|
614
|
+
const imageFile = bucket.file(imagePath)
|
615
|
+
const [exists] = await imageFile.exists()
|
616
|
+
if (!exists) {
|
617
|
+
// Descargar la imagen
|
618
|
+
const response = await fetch(imageUrl)
|
619
|
+
if (!response.ok) {
|
620
|
+
return res.status(400).json({
|
621
|
+
status: "ERROR",
|
622
|
+
message: "No se pudo descargar la imagen",
|
623
|
+
})
|
624
|
+
}
|
625
|
+
|
626
|
+
const buffer = await response.arrayBuffer()
|
627
|
+
|
628
|
+
// Guardar la imagen en el bucket
|
629
|
+
await imageFile.save(new Uint8Array(buffer), {
|
630
|
+
contentType: "image/png",
|
631
|
+
})
|
632
|
+
}
|
633
|
+
|
634
|
+
emitToNotification(imageId, {
|
635
|
+
status: "SUCCESS",
|
636
|
+
message: "Image generated successfully",
|
637
|
+
})
|
638
|
+
res.json({ status: "SUCCESS" })
|
639
|
+
})
|
640
|
+
|
644
641
|
app.post(
|
645
642
|
"/webhooks/:courseSlug/exercise-processor/:lessonID/:rigoToken",
|
646
643
|
async (req, res) => {
|
@@ -851,28 +848,50 @@ export default class ServeCommand extends SessionCommand {
|
|
851
848
|
const courseSlug = req.query.slug
|
852
849
|
const lang = req.query.lang || "us"
|
853
850
|
|
851
|
+
if (!courseSlug) {
|
852
|
+
return res.status(400).json({ error: "Missing courseSlug" })
|
853
|
+
}
|
854
|
+
|
854
855
|
const basePath = `courses/${courseSlug}/exercises/${slug}/`
|
855
|
-
const
|
856
|
+
const prefix = basePath + "README"
|
856
857
|
|
857
|
-
|
858
|
+
try {
|
859
|
+
const [files] = await bucket.getFiles({ prefix })
|
858
860
|
|
859
|
-
|
861
|
+
const readmeFiles = files.map(f => f.name)
|
860
862
|
|
861
|
-
|
862
|
-
|
863
|
-
} catch {
|
864
|
-
if (lang !== "us") {
|
865
|
-
console.warn(`No README for lang '${lang}', falling back to 'us'`)
|
866
|
-
const fallbackFile = bucket.file(basePath + "README.md")
|
867
|
-
contentBuffer = await fallbackFile.download()
|
868
|
-
} else {
|
869
|
-
return res.status(404).json({ error: "README not found" })
|
863
|
+
if (readmeFiles.length === 0) {
|
864
|
+
return res.status(404).json({ error: "No README files found" })
|
870
865
|
}
|
871
|
-
}
|
872
866
|
|
873
|
-
|
867
|
+
const requestedFilename =
|
868
|
+
lang === "us" || lang === "en" ?
|
869
|
+
`${basePath}README.md` :
|
870
|
+
`${basePath}README.${lang}.md`
|
871
|
+
|
872
|
+
let selectedFile = readmeFiles.find(f => f === requestedFilename)
|
873
|
+
|
874
|
+
if (!selectedFile) {
|
875
|
+
selectedFile = readmeFiles[0]
|
876
|
+
console.warn(
|
877
|
+
`Requested README not found for lang '${lang}', using '${selectedFile}'`
|
878
|
+
)
|
879
|
+
}
|
880
|
+
|
881
|
+
let foundLang = "us"
|
882
|
+
const match = selectedFile.match(/readme(?:\.([a-z]{2}))?\.md$/i)
|
883
|
+
if (match && match[1]) {
|
884
|
+
foundLang = match[1].toLowerCase()
|
885
|
+
}
|
874
886
|
|
875
|
-
|
887
|
+
const [contentBuffer] = await bucket.file(selectedFile).download()
|
888
|
+
const { attributes, body } = frontMatter(contentBuffer.toString())
|
889
|
+
|
890
|
+
res.send({ attributes, body, lang: foundLang })
|
891
|
+
} catch (error) {
|
892
|
+
console.error(error)
|
893
|
+
res.status(500).json({ error: "Internal server error" })
|
894
|
+
}
|
876
895
|
})
|
877
896
|
|
878
897
|
app.get("/.learn/assets/:file", async (req, res) => {
|
@@ -906,7 +925,7 @@ export default class ServeCommand extends SessionCommand {
|
|
906
925
|
console.log(`PUT /exercise/${slug}/file/${fileName}`)
|
907
926
|
|
908
927
|
const courseSlug = query.slug
|
909
|
-
console.log("COURSE SLUG", courseSlug)
|
928
|
+
// console.log("COURSE SLUG", courseSlug)
|
910
929
|
|
911
930
|
// Update the file in the bucket
|
912
931
|
const file = await bucket.file(
|
@@ -914,7 +933,7 @@ export default class ServeCommand extends SessionCommand {
|
|
914
933
|
)
|
915
934
|
await file.save(req.body)
|
916
935
|
const created = await file.exists()
|
917
|
-
console.log("File updated", created)
|
936
|
+
// console.log("File updated", created)
|
918
937
|
res.send({
|
919
938
|
message: "File updated",
|
920
939
|
created,
|
@@ -1412,12 +1431,30 @@ export default class ServeCommand extends SessionCommand {
|
|
1412
1431
|
|
1413
1432
|
copyDir(uiSrc, buildRoot)
|
1414
1433
|
|
1434
|
+
const availableLangs = Object.keys(config.title)
|
1435
|
+
|
1436
|
+
let selectedLang = "us"
|
1437
|
+
let title = ""
|
1438
|
+
if (availableLangs.includes("us")) {
|
1439
|
+
title = config.title.us
|
1440
|
+
} else {
|
1441
|
+
// Select the first available lang
|
1442
|
+
title = config.title[availableLangs[0]]
|
1443
|
+
|
1444
|
+
selectedLang = availableLangs[0]
|
1445
|
+
}
|
1446
|
+
|
1447
|
+
console.log(config.description, "CONFIG DESCRIPTION")
|
1448
|
+
// console.log(availableLangs, "AVAILABLE LANGs")
|
1449
|
+
// console.log(selectedLang, "SELECTED LANG")
|
1450
|
+
// console.log(title, "TITLE")
|
1451
|
+
|
1415
1452
|
// 5) Inyectar placeholders en index.html
|
1416
1453
|
const idxTpl = fs.readFileSync(path.join(uiSrc, "index.html"), "utf-8")
|
1417
1454
|
const idxHtml = idxTpl
|
1418
|
-
.replace(/{{title}}/g,
|
1419
|
-
.replace(/<title>.*<\/title>/, `<title>${
|
1420
|
-
.replace(/{{description}}/g, config.description
|
1455
|
+
.replace(/{{title}}/g, title)
|
1456
|
+
.replace(/<title>.*<\/title>/, `<title>${title}</title>`)
|
1457
|
+
.replace(/{{description}}/g, config.description[selectedLang])
|
1421
1458
|
.replace(
|
1422
1459
|
/{{preview}}/g,
|
1423
1460
|
fixPreviewUrl(slug, "") ||
|
@@ -181,6 +181,9 @@ const FileUploader: React.FC<FileUploaderProps> = ({
|
|
181
181
|
const setUploadedFiles = useStore((state) => state.setUploadedFiles)
|
182
182
|
const [isDragging, setIsDragging] = useState(false)
|
183
183
|
const [isLoading, setIsLoading] = useState(false)
|
184
|
+
const [limitExceededBehavior, setLimitExceededBehavior] = useState<
|
185
|
+
"firstImages" | "cancel"
|
186
|
+
>("firstImages")
|
184
187
|
|
185
188
|
const extractTextFromFile = async (file: File): Promise<ParsedFile> => {
|
186
189
|
const { type, name } = file
|
@@ -203,6 +206,7 @@ const FileUploader: React.FC<FileUploaderProps> = ({
|
|
203
206
|
: window.location.origin
|
204
207
|
}/notifications/${resultId}`
|
205
208
|
formData.append("webhook_callback_url", webhookUrl)
|
209
|
+
formData.append("limit_exceeded_behavior", limitExceededBehavior)
|
206
210
|
|
207
211
|
const loadingToast = toast.loading(`Processing ${file.name}...`)
|
208
212
|
try {
|
@@ -226,9 +230,17 @@ const FileUploader: React.FC<FileUploaderProps> = ({
|
|
226
230
|
notificationId: resultId,
|
227
231
|
}
|
228
232
|
} catch (err: any) {
|
229
|
-
|
230
|
-
|
231
|
-
|
233
|
+
console.log(err.response.data, "ERROR IN FILE UPLOADER")
|
234
|
+
if (err.response.data.error_code === "too_many_images") {
|
235
|
+
toast.error(`❌ ${t("uploader.files.maxImagesPerPDFError")}`, {
|
236
|
+
id: loadingToast,
|
237
|
+
})
|
238
|
+
} else {
|
239
|
+
toast.error(t("uploader.files.errorProcessingPDF"), {
|
240
|
+
id: loadingToast,
|
241
|
+
})
|
242
|
+
}
|
243
|
+
|
232
244
|
return { name, text: "", status: "ERROR", notificationId: "" }
|
233
245
|
}
|
234
246
|
}
|
@@ -309,6 +321,26 @@ const FileUploader: React.FC<FileUploaderProps> = ({
|
|
309
321
|
onDrop={handleDrop}
|
310
322
|
className={isDragging ? "border-blue-600 bg-blue-50" : ""}
|
311
323
|
/>
|
324
|
+
<p className="text-xs text-gray-500">
|
325
|
+
{t("uploader.files.maxImagesPerPDFWarning")}
|
326
|
+
|
327
|
+
<select
|
328
|
+
className="bg-white text-black ml-2 p-1 rounded-md"
|
329
|
+
value={limitExceededBehavior}
|
330
|
+
onChange={(e) =>
|
331
|
+
setLimitExceededBehavior(
|
332
|
+
e.target.value as "firstImages" | "cancel"
|
333
|
+
)
|
334
|
+
}
|
335
|
+
>
|
336
|
+
<option value="firstImages">
|
337
|
+
{t("uploader.files.useOnlyFirstImages")}
|
338
|
+
</option>
|
339
|
+
<option value="cancel">
|
340
|
+
{t("uploader.files.cancelAndUploadAnother")}
|
341
|
+
</option>
|
342
|
+
</select>
|
343
|
+
</p>
|
312
344
|
<button
|
313
345
|
disabled={uploadedFiles.some((file) => file.status !== "SUCCESS")}
|
314
346
|
className="bg-blue-500 text-white px-4 py-2 rounded-md cursor-pointer disabled:opacity-50"
|
@@ -54,10 +54,15 @@
|
|
54
54
|
},
|
55
55
|
"files": {
|
56
56
|
"description": "Upload files",
|
57
|
-
"descriptionLong": "Upload a PDF
|
57
|
+
"descriptionLong": "Upload a PDF file or drag it here",
|
58
58
|
"processing": "Processing...",
|
59
59
|
"drop": "Drop it here",
|
60
|
-
"finish": "🚀 Finish"
|
60
|
+
"finish": "🚀 Finish",
|
61
|
+
"maxImagesPerPDFWarning": "⚠️ Only 15 images per PDF are supported in LearnPack beta. You can select what to do if the PDF exceeds this limit.",
|
62
|
+
"useOnlyFirstImages": "Use only the first 15 images",
|
63
|
+
"cancelAndUploadAnother": "Cancel and upload another PDF",
|
64
|
+
"maxImagesPerPDFError": "❌ Only 15 images per PDF are supported in LearnPack beta and this PDF exceeds the limit.",
|
65
|
+
"errorProcessingPDF": "❌ Error processing PDF, please try again, if the problem persists, try with a different file."
|
61
66
|
},
|
62
67
|
"youtube": {
|
63
68
|
"description": "Share a Youtube link",
|
@@ -110,4 +115,4 @@
|
|
110
115
|
"youDontHaveAnAccount": "You don't have an account?",
|
111
116
|
"registerHere": "Register here."
|
112
117
|
}
|
113
|
-
}
|
118
|
+
}
|
@@ -54,10 +54,15 @@
|
|
54
54
|
},
|
55
55
|
"files": {
|
56
56
|
"description": "Subir archivos",
|
57
|
-
"descriptionLong": "Subir un archivo PDF o
|
57
|
+
"descriptionLong": "Subir un archivo PDF o arrastralo aquí",
|
58
58
|
"processing": "Procesando...",
|
59
59
|
"drop": "Arrastra el archivo aquí",
|
60
|
-
"finish": "🚀 Finalizar"
|
60
|
+
"finish": "🚀 Finalizar",
|
61
|
+
"maxImagesPerPDFWarning": "⚠️ Solo se admiten 15 imágenes por PDF en LearnPack beta. Puedes seleccionar qué hacer si el PDF excede este límite.",
|
62
|
+
"useOnlyFirstImages": "Usar solo las primeras 15 imágenes",
|
63
|
+
"cancelAndUploadAnother": "Cancelar y subir otro PDF",
|
64
|
+
"maxImagesPerPDFError": "❌ Solo se admiten 15 imágenes por PDF en LearnPack beta y este PDF excede el límite.",
|
65
|
+
"errorProcessingPDF": "❌ Error procesando PDF, por favor intenta de nuevo, si el problema persiste, intenta con un archivo diferente."
|
61
66
|
},
|
62
67
|
"youtube": {
|
63
68
|
"description": "Compartir un enlace de Youtube",
|
@@ -2,7 +2,8 @@ export const DEV_MODE = false
|
|
2
2
|
|
3
3
|
export const RIGOBOT_HOST = DEV_MODE
|
4
4
|
? "https://rigobot-test-cca7d841c9d8.herokuapp.com"
|
5
|
-
: "https://rigobot.
|
5
|
+
: // "https://8000-charlytoc-rigobot-bmwdeam7cev.ws-us120.gitpod.io"
|
6
|
+
"https://rigobot.herokuapp.com"
|
6
7
|
|
7
8
|
export const BREATHECODE_HOST = DEV_MODE
|
8
9
|
? "https://breathecode-test.herokuapp.com"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import axios from "axios"
|
2
|
-
import { BREATHECODE_HOST, RIGOBOT_HOST } from "./constants"
|
2
|
+
import { BREATHECODE_HOST, DEV_MODE, RIGOBOT_HOST } from "./constants"
|
3
3
|
import { Lesson } from "../components/LessonItem"
|
4
4
|
import { randomUUID } from "./creatorUtils"
|
5
5
|
import { Syllabus } from "./store"
|
@@ -267,6 +267,13 @@ export function getFilenameFromUrl(url: string): string {
|
|
267
267
|
}
|
268
268
|
}
|
269
269
|
|
270
|
+
export const makeCallbackUrl = (slug: string) => {
|
271
|
+
if (DEV_MODE) {
|
272
|
+
return `https://8000-charlytoc-rigobot-bmwdeam7cev.ws-us120.gitpod.io/v1/learnpack/tools/images/callback?slug=${slug}`
|
273
|
+
}
|
274
|
+
return `${window.location.origin}/api/v1/webhooks/images`
|
275
|
+
}
|
276
|
+
|
270
277
|
type TGenerateImageParams = {
|
271
278
|
prompt: string
|
272
279
|
}
|
@@ -280,6 +287,7 @@ export const generateImage = async (
|
|
280
287
|
`${RIGOBOT_HOST}/v1/learnpack/tools/images`,
|
281
288
|
{
|
282
289
|
prompt,
|
290
|
+
webhook_callback_url: "https://www.learnpack.co/api/v1/webhooks/images",
|
283
291
|
},
|
284
292
|
{
|
285
293
|
headers: {
|