@learnpack/learnpack 5.0.238 → 5.0.244
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/commands/init.js +7 -2
- package/lib/commands/publish.d.ts +1 -1
- package/lib/commands/publish.js +22 -16
- package/lib/commands/serve.d.ts +1 -2
- package/lib/commands/serve.js +128 -71
- package/lib/creatorDist/assets/{index-x_kA-1DY.js → index-BWHp9KF3.js} +3045 -3040
- package/lib/creatorDist/index.html +1 -1
- package/lib/models/creator.d.ts +1 -0
- package/lib/utils/api.d.ts +2 -0
- package/lib/utils/api.js +1 -0
- package/lib/utils/creatorSocket.d.ts +1 -1
- package/lib/utils/creatorSocket.js +10 -3
- package/lib/utils/rigoActions.d.ts +11 -1
- package/lib/utils/rigoActions.js +29 -2
- package/package.json +1 -1
- package/src/commands/init.ts +12 -2
- package/src/commands/publish.ts +36 -26
- package/src/commands/serve.ts +223 -106
- package/src/creator/src/App.tsx +3 -1
- package/src/creator/src/components/NotificationListener.tsx +1 -1
- package/src/creator/src/components/syllabus/SyllabusEditor.tsx +11 -13
- package/src/creator/src/utils/rigo.ts +4 -2
- package/src/creator/src/utils/store.ts +4 -1
- package/src/creatorDist/assets/{index-x_kA-1DY.js → index-BWHp9KF3.js} +3045 -3040
- package/src/creatorDist/index.html +1 -1
- package/src/models/creator.ts +1 -0
- package/src/ui/_app/app.js +232 -232
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/api.ts +3 -0
- package/src/utils/creatorSocket.ts +22 -16
- package/src/utils/rigoActions.ts +54 -1
- package/oclif.manifest.json +0 -1
package/lib/commands/init.js
CHANGED
@@ -270,8 +270,12 @@ const handleAILogic = async (tutorialDir, packageInfo) => {
|
|
270
270
|
const imagePromises = imagesArray.map(async (image) => {
|
271
271
|
try {
|
272
272
|
const filename = (0, creatorUtilities_1.getFilenameFromUrl)(image.url);
|
273
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${(0, creatorUtilities_1.slugify)(packageInfo.title.us)}/images/${filename}`;
|
273
274
|
const imagePath = path.join(tutorialDir, ".learn", "assets", filename);
|
274
|
-
const res = await (0, rigoActions_1.generateImage)(rigoToken, {
|
275
|
+
const res = await (0, rigoActions_1.generateImage)(rigoToken, {
|
276
|
+
prompt: image.alt,
|
277
|
+
callbackUrl: webhookUrl,
|
278
|
+
});
|
275
279
|
await (0, rigoActions_1.downloadImage)(res.image_url, imagePath);
|
276
280
|
return true;
|
277
281
|
}
|
@@ -289,8 +293,9 @@ const handleAILogic = async (tutorialDir, packageInfo) => {
|
|
289
293
|
prompt: "Generate a preview image for the tutorial. This is all the tutorial information: " +
|
290
294
|
packageContext +
|
291
295
|
"\n Generate only a basic preview image, add the tutorial Title as a text add the top middle, avoid adding any other text elements. Try to generate an image that related with the tutorial content.",
|
296
|
+
callbackUrl: `${process.env.HOST}/webhooks/${(0, creatorUtilities_1.slugify)(packageInfo.title.us)}/images/preview.png`,
|
292
297
|
});
|
293
|
-
await
|
298
|
+
// await downloadImage(res.image_url, imagePath)
|
294
299
|
return true;
|
295
300
|
};
|
296
301
|
const getChoices = async (empty) => {
|
@@ -2,7 +2,7 @@ import SessionCommand from "../utils/SessionCommand";
|
|
2
2
|
export declare const handleAssetCreation: (sessionPayload: {
|
3
3
|
token: string;
|
4
4
|
rigobotToken: string;
|
5
|
-
}, learnJson: any, selectedLang: string, learnpackDeployUrl: string) => Promise<
|
5
|
+
}, learnJson: any, selectedLang: string, learnpackDeployUrl: string, b64IndexReadme: string, all_translations?: string[]) => Promise<any>;
|
6
6
|
declare class BuildCommand extends SessionCommand {
|
7
7
|
static description: string;
|
8
8
|
static flags: {
|
package/lib/commands/publish.js
CHANGED
@@ -18,11 +18,12 @@ const api_1 = require("../utils/api");
|
|
18
18
|
const prompts = require("prompts");
|
19
19
|
const rigoActions_1 = require("../utils/rigoActions");
|
20
20
|
const misc_1 = require("../utils/misc");
|
21
|
+
const creatorUtilities_1 = require("../utils/creatorUtilities");
|
21
22
|
const uploadZipEndpont = api_1.RIGOBOT_HOST + "/v1/learnpack/upload";
|
22
|
-
const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, learnpackDeployUrl) => {
|
23
|
+
const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, learnpackDeployUrl, b64IndexReadme, all_translations = []) => {
|
23
24
|
const categories = {
|
24
|
-
us:
|
25
|
-
es:
|
25
|
+
us: 9,
|
26
|
+
es: 10,
|
26
27
|
};
|
27
28
|
let category = categories[selectedLang];
|
28
29
|
if (!category) {
|
@@ -30,11 +31,12 @@ const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, lear
|
|
30
31
|
}
|
31
32
|
try {
|
32
33
|
const user = await api_1.default.validateToken(sessionPayload.token);
|
33
|
-
const
|
34
|
+
const slug = (0, creatorUtilities_1.slugify)(learnJson.title[selectedLang]).slice(0, 50);
|
35
|
+
const { exists } = await api_1.default.doesAssetExists(sessionPayload.token, slug);
|
34
36
|
if (!exists) {
|
35
37
|
console_1.default.info("Asset does not exist in this academy, creating it");
|
36
38
|
const asset = await api_1.default.createAsset(sessionPayload.token, {
|
37
|
-
slug:
|
39
|
+
slug: slug,
|
38
40
|
title: learnJson.title[selectedLang],
|
39
41
|
lang: selectedLang,
|
40
42
|
description: learnJson.description[selectedLang],
|
@@ -45,23 +47,27 @@ const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, lear
|
|
45
47
|
owner: user.id,
|
46
48
|
author: user.id,
|
47
49
|
preview: learnJson.preview,
|
50
|
+
readme_raw: b64IndexReadme,
|
51
|
+
all_translations,
|
48
52
|
});
|
49
53
|
await api_1.default.updateRigoAssetID(sessionPayload.token, learnJson.slug, asset.id);
|
50
54
|
console_1.default.info("Asset created with id", asset.id);
|
55
|
+
return asset;
|
51
56
|
}
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
console_1.default.info("Asset exists, updating it");
|
58
|
+
const asset = await api_1.default.updateAsset(sessionPayload.token, slug, {
|
59
|
+
learnpack_deploy_url: learnpackDeployUrl,
|
60
|
+
title: learnJson.title[selectedLang],
|
61
|
+
description: learnJson.description[selectedLang],
|
62
|
+
all_translations,
|
63
|
+
});
|
64
|
+
await api_1.default.updateRigoAssetID(sessionPayload.rigobotToken.trim(), learnJson.slug, asset.id);
|
65
|
+
console_1.default.info("Asset updated with id", asset.id);
|
66
|
+
return asset;
|
62
67
|
}
|
63
68
|
catch (error) {
|
64
69
|
console_1.default.error("Error updating or creating asset:", error);
|
70
|
+
return null;
|
65
71
|
}
|
66
72
|
};
|
67
73
|
exports.handleAssetCreation = handleAssetCreation;
|
@@ -295,7 +301,7 @@ class BuildCommand extends SessionCommand_1.default {
|
|
295
301
|
console.log(res.data);
|
296
302
|
fs.unlinkSync(zipFilePath);
|
297
303
|
this.removeDirectory(buildDir);
|
298
|
-
await (0, exports.handleAssetCreation)(sessionPayload, learnJson, "us", res.data.url);
|
304
|
+
await (0, exports.handleAssetCreation)(sessionPayload, learnJson, "us", res.data.url, "", []);
|
299
305
|
}
|
300
306
|
catch (error) {
|
301
307
|
if (axios_1.default.isAxiosError(error)) {
|
package/lib/commands/serve.d.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import SessionCommand from "../utils/SessionCommand";
|
2
|
-
import { Bucket } from "@google-cloud/storage";
|
3
2
|
import { FormState } from "../models/creator";
|
4
3
|
export declare const createLearnJson: (courseInfo: FormState) => {
|
5
4
|
slug: string;
|
@@ -20,7 +19,7 @@ export declare const createLearnJson: (courseInfo: FormState) => {
|
|
20
19
|
};
|
21
20
|
preview: string;
|
22
21
|
};
|
23
|
-
export declare const processImage: (
|
22
|
+
export declare const processImage: (url: string, description: string, rigoToken: string, courseSlug: string) => Promise<boolean>;
|
24
23
|
export default class ServeCommand extends SessionCommand {
|
25
24
|
static description: string;
|
26
25
|
static flags: any;
|
package/lib/commands/serve.js
CHANGED
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.processImage = exports.createLearnJson = void 0;
|
4
4
|
const tslib_1 = require("tslib");
|
5
5
|
const command_1 = require("@oclif/command");
|
6
|
-
// import { readDocument } from "../utils/readDocuments"
|
7
6
|
const youtube_transcript_1 = require("youtube-transcript");
|
8
7
|
const express = require("express");
|
9
8
|
const cors = require("cors");
|
@@ -42,11 +41,11 @@ function findLast(array, predicate) {
|
|
42
41
|
}
|
43
42
|
const createLearnJson = (courseInfo) => {
|
44
43
|
// console.log("courseInfo to create learn json", courseInfo)
|
45
|
-
const expectedPreviewUrl = `https://${
|
44
|
+
const expectedPreviewUrl = `https://${courseInfo.slug}.learn-pack.com/preview.png`;
|
46
45
|
console.log("Preview url in generated learn.json", expectedPreviewUrl);
|
47
46
|
const language = courseInfo.language || "en";
|
48
47
|
const learnJson = {
|
49
|
-
slug:
|
48
|
+
slug: courseInfo.slug,
|
50
49
|
title: language === "en" || language === "us" ?
|
51
50
|
{
|
52
51
|
us: courseInfo.title,
|
@@ -72,19 +71,6 @@ const uploadFileToBucket = async (bucket, file, path) => {
|
|
72
71
|
const fileRef = bucket.file(path);
|
73
72
|
await fileRef.save(Buffer.from(file, "utf8"));
|
74
73
|
};
|
75
|
-
const uploadImageToBucket = async (bucket, url, path) => {
|
76
|
-
const response = await fetch(url);
|
77
|
-
if (!response.ok) {
|
78
|
-
throw new Error(`Failed to download image: ${response.statusText}`);
|
79
|
-
}
|
80
|
-
const contentType = response.headers.get("content-type") || "application/octet-stream";
|
81
|
-
const buffer = await response.arrayBuffer();
|
82
|
-
const fileRef = bucket.file(path);
|
83
|
-
await fileRef.save(Buffer.from(buffer), {
|
84
|
-
resumable: false,
|
85
|
-
contentType,
|
86
|
-
});
|
87
|
-
};
|
88
74
|
const PARAMS = {
|
89
75
|
expected_grade_level: "8",
|
90
76
|
max_fkgl: 10,
|
@@ -92,16 +78,16 @@ const PARAMS = {
|
|
92
78
|
max_rewrite_attempts: 2,
|
93
79
|
max_title_length: 50,
|
94
80
|
};
|
95
|
-
const processImage = async (
|
81
|
+
const processImage = async (url, description, rigoToken, courseSlug) => {
|
96
82
|
try {
|
97
83
|
// TODO: MAKE THIS ASYNC
|
98
84
|
const filename = (0, creatorUtilities_1.getFilenameFromUrl)(url);
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
console.log("✅ Image", imagePath, "generated successfully!")
|
85
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${courseSlug}/images/${filename}`;
|
86
|
+
await (0, rigoActions_1.generateImage)(rigoToken, {
|
87
|
+
prompt: description,
|
88
|
+
callbackUrl: webhookUrl,
|
89
|
+
});
|
90
|
+
// console.log("✅ Image", imagePath, "generated successfully!")
|
105
91
|
return true;
|
106
92
|
}
|
107
93
|
catch (_a) {
|
@@ -131,10 +117,31 @@ const uploadInitialReadme = async (bucket, exSlug, targetDir, packageContext) =>
|
|
131
117
|
await uploadFileToBucket(bucket, isGeneratingText, `${targetDir}/${readmeFilename}`);
|
132
118
|
};
|
133
119
|
const cleanFormState = (formState) => {
|
134
|
-
// keysToDelete: description, technologies, purpose
|
135
120
|
const { description, technologies, purpose, hasContentIndex, duration, isCompleted, variables, currentStep, language } = formState, rest = tslib_1.__rest(formState, ["description", "technologies", "purpose", "hasContentIndex", "duration", "isCompleted", "variables", "currentStep", "language"]);
|
136
121
|
return rest;
|
137
122
|
};
|
123
|
+
const createMultiLangAsset = async (bucket, rigoToken, bcToken, courseSlug, courseJson, deployUrl) => {
|
124
|
+
const availableLangs = Object.keys(courseJson.title);
|
125
|
+
console.log("AVAILABLE LANGUAGES to upload asset", availableLangs);
|
126
|
+
const all_translations = [];
|
127
|
+
for (const lang of availableLangs) {
|
128
|
+
// eslint-disable-next-line no-await-in-loop
|
129
|
+
const indexReadme = await bucket.file(`courses/${courseSlug}/README.${lang === "us" || lang === "en" ? "md" : `${lang}.md`}`);
|
130
|
+
// eslint-disable-next-line no-await-in-loop
|
131
|
+
const [indexReadmeContent] = await indexReadme.download();
|
132
|
+
const indexReadmeString = indexReadmeContent.toString();
|
133
|
+
const b64IndexReadme = Buffer.from(indexReadmeString).toString("base64");
|
134
|
+
// eslint-disable-next-line no-await-in-loop
|
135
|
+
const asset = await (0, publish_1.handleAssetCreation)({ token: bcToken, rigobotToken: rigoToken }, courseJson, lang, deployUrl, b64IndexReadme, all_translations);
|
136
|
+
all_translations.push(asset.slug);
|
137
|
+
}
|
138
|
+
// const languageCodes = new Set(languageCodes)
|
139
|
+
// const asset = await api.createAsset(rigoToken, {
|
140
|
+
// slug: courseSlug,
|
141
|
+
// title: courseJson.title,
|
142
|
+
// description: courseJson.description,
|
143
|
+
// })
|
144
|
+
};
|
138
145
|
async function startExerciseGeneration(bucket, rigoToken, steps, packageContext, exercise, tutorialDir, courseSlug, purposeSlug, lastLesson = "") {
|
139
146
|
const exSlug = (0, creatorUtilities_2.slugify)(exercise.id + "-" + exercise.title);
|
140
147
|
console.log("Starting generation of", exSlug);
|
@@ -150,6 +157,19 @@ async function startExerciseGeneration(bucket, rigoToken, steps, packageContext,
|
|
150
157
|
last_lesson: lastLesson,
|
151
158
|
}, purposeSlug, webhookUrl);
|
152
159
|
}
|
160
|
+
async function createInitialReadme(tutorialInfo, tutorialSlug, rigoToken) {
|
161
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${tutorialSlug}/initial-readme-processor`;
|
162
|
+
console.log("Creating initial readme", webhookUrl);
|
163
|
+
try {
|
164
|
+
const res = await (0, rigoActions_1.createStructuredPreviewReadme)(rigoToken, {
|
165
|
+
tutorial_info: tutorialInfo,
|
166
|
+
}, webhookUrl);
|
167
|
+
console.log("Initial readme created", res);
|
168
|
+
}
|
169
|
+
catch (error) {
|
170
|
+
console.error("Error creating initial readme", error);
|
171
|
+
}
|
172
|
+
}
|
153
173
|
const fixPreviewUrl = (slug, previewUrl) => {
|
154
174
|
if (!previewUrl) {
|
155
175
|
return null;
|
@@ -315,6 +335,19 @@ class ServeCommand extends SessionCommand_1.default {
|
|
315
335
|
(0, creatorSocket_1.emitToNotification)(id, body);
|
316
336
|
res.json({ id, status: "SUCCESS" });
|
317
337
|
});
|
338
|
+
app.post("/webhooks/:courseSlug/initial-readme-processor", async (req, res) => {
|
339
|
+
const { courseSlug } = req.params;
|
340
|
+
const body = req.body;
|
341
|
+
// Save the file as courses/courseSlug/README.md
|
342
|
+
const filePath = `courses/${courseSlug}/README.${body.parsed.language_code === "us" ||
|
343
|
+
body.parsed.language_code === "en" ?
|
344
|
+
"md" :
|
345
|
+
`${body.parsed.language_code}.md`}`;
|
346
|
+
console.log("Saving initial readme to", filePath);
|
347
|
+
await uploadFileToBucket(bucket, body.parsed.content, filePath);
|
348
|
+
console.log("Initial readme saved to", filePath);
|
349
|
+
res.json({ status: "SUCCESS" });
|
350
|
+
});
|
318
351
|
app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
|
319
352
|
const { courseSlug, imageId } = req.params;
|
320
353
|
const body = req.body;
|
@@ -401,7 +434,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
401
434
|
});
|
402
435
|
for (const image of imagesArray) {
|
403
436
|
// eslint-disable-next-line no-await-in-loop
|
404
|
-
await (0, exports.processImage)(
|
437
|
+
await (0, exports.processImage)(image.url, image.alt, rigoToken, courseSlug);
|
405
438
|
}
|
406
439
|
}
|
407
440
|
(0, creatorSocket_1.emitToCourse)(courseSlug, "course-creation", {
|
@@ -572,19 +605,23 @@ class ServeCommand extends SessionCommand_1.default {
|
|
572
605
|
});
|
573
606
|
app.post("/actions/translate", express.json(), async (req, res) => {
|
574
607
|
console.log("POST /actions/translate");
|
575
|
-
const { exerciseSlugs, languages, rigoToken } = req.body;
|
608
|
+
const { exerciseSlugs, languages, rigoToken, currentLanguage } = req.body;
|
576
609
|
const query = req.query;
|
577
610
|
const courseSlug = query.slug;
|
578
|
-
console.log("EXERCISE SLUGS", exerciseSlugs);
|
579
|
-
console.log("LANGUAGES", languages);
|
580
|
-
console.log("RIGO TOKEN", rigoToken);
|
581
611
|
if (!rigoToken) {
|
582
612
|
return res.status(400).json({ error: "RigoToken not found" });
|
583
613
|
}
|
584
614
|
const languagesToTranslate = languages.split(",");
|
615
|
+
const course = await bucket
|
616
|
+
.file(`courses/${courseSlug}/learn.json`)
|
617
|
+
.download();
|
618
|
+
const courseJson = JSON.parse(course.toString());
|
619
|
+
const languageCodes = new Set();
|
585
620
|
try {
|
586
621
|
await Promise.all(exerciseSlugs.map(async (slug) => {
|
587
|
-
const readmePath = `courses/${courseSlug}/exercises/${slug}/README
|
622
|
+
const readmePath = `courses/${courseSlug}/exercises/${slug}/README${currentLanguage === "us" || currentLanguage === "en" ?
|
623
|
+
"" :
|
624
|
+
`.${currentLanguage}`}.md`;
|
588
625
|
const readme = await bucket.file(readmePath).download();
|
589
626
|
await Promise.all(languagesToTranslate.map(async (language) => {
|
590
627
|
const response = await (0, rigoActions_1.translateExercise)(rigoToken, {
|
@@ -592,10 +629,62 @@ class ServeCommand extends SessionCommand_1.default {
|
|
592
629
|
output_language: language,
|
593
630
|
exercise_slug: slug,
|
594
631
|
});
|
595
|
-
const translatedReadme = await bucket.file(`courses/${courseSlug}/exercises/${slug}/README
|
632
|
+
const translatedReadme = await bucket.file(`courses/${courseSlug}/exercises/${slug}/README${response.parsed.output_language_code === "us" ||
|
633
|
+
response.parsed.output_language_code === "en" ?
|
634
|
+
"" :
|
635
|
+
`.${response.parsed.output_language_code}`}.md`);
|
596
636
|
await translatedReadme.save(response.parsed.translation);
|
637
|
+
languageCodes.add(response.parsed.output_language_code);
|
597
638
|
}));
|
598
639
|
}));
|
640
|
+
if (languageCodes.has("en")) {
|
641
|
+
languageCodes.delete("en");
|
642
|
+
languageCodes.add("us");
|
643
|
+
}
|
644
|
+
const currentLanguages = Object.keys(courseJson.title);
|
645
|
+
for (const languageCode of currentLanguages) {
|
646
|
+
if (languageCodes.has(languageCode)) {
|
647
|
+
languageCodes.delete(languageCode);
|
648
|
+
}
|
649
|
+
}
|
650
|
+
if ([...languageCodes].length > 0) {
|
651
|
+
console.log("TRANSLATING COURSE METADATA", languageCodes);
|
652
|
+
const translatedCourseMetadata = await Promise.all([...languageCodes].map(async (languageCode) => {
|
653
|
+
const result = await (0, rigoActions_1.translateCourseMetadata)(rigoToken, {
|
654
|
+
title: courseJson.title[currentLanguage],
|
655
|
+
description: courseJson.description[currentLanguage],
|
656
|
+
destination_lang_code: languageCode,
|
657
|
+
});
|
658
|
+
return {
|
659
|
+
languageCode,
|
660
|
+
title: result.parsed.title,
|
661
|
+
description: result.parsed.description,
|
662
|
+
};
|
663
|
+
}));
|
664
|
+
for (const metadata of translatedCourseMetadata) {
|
665
|
+
courseJson.title[metadata.languageCode] = metadata.title;
|
666
|
+
courseJson.description[metadata.languageCode] =
|
667
|
+
metadata.description;
|
668
|
+
}
|
669
|
+
await uploadFileToBucket(bucket, JSON.stringify(courseJson), `courses/${courseSlug}/learn.json`);
|
670
|
+
const previewReadme = await bucket.file(`courses/${courseSlug}/README${currentLanguage === "us" || currentLanguage === "en" ?
|
671
|
+
"" :
|
672
|
+
`.${currentLanguage}`}.md`);
|
673
|
+
const [previewReadmeContent] = await previewReadme.download();
|
674
|
+
const previewReadmeContentString = previewReadmeContent.toString();
|
675
|
+
await Promise.all([...languageCodes].map(async (languageCode) => {
|
676
|
+
const translatedPreviewReadme = await (0, rigoActions_1.translateExercise)(rigoToken, {
|
677
|
+
text_to_translate: previewReadmeContentString,
|
678
|
+
output_language: languageCode,
|
679
|
+
exercise_slug: "preview-readme",
|
680
|
+
});
|
681
|
+
await bucket
|
682
|
+
.file(`courses/${courseSlug}/README${languageCode === "us" || languageCode === "en" ?
|
683
|
+
"" :
|
684
|
+
`.${languageCode}`}.md`)
|
685
|
+
.save(translatedPreviewReadme.parsed.translation);
|
686
|
+
}));
|
687
|
+
}
|
599
688
|
return res.status(200).json({ message: "Translated exercises" });
|
600
689
|
}
|
601
690
|
catch (error) {
|
@@ -604,6 +693,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
604
693
|
}
|
605
694
|
});
|
606
695
|
app.delete("/exercise/:slug/delete", async (req, res) => {
|
696
|
+
console.log("DELETE /exercise/:slug/delete");
|
607
697
|
const { slug } = req.params;
|
608
698
|
const query = req.query;
|
609
699
|
const courseSlug = query.slug;
|
@@ -639,53 +729,23 @@ class ServeCommand extends SessionCommand_1.default {
|
|
639
729
|
}
|
640
730
|
catch (error) {
|
641
731
|
if (error.code === 404) {
|
642
|
-
console.log("SIDEBAR FILE NOT FOUND", courseSlug);
|
643
732
|
const { exercises } = await (0, configBuilder_1.buildConfig)(bucket, courseSlug);
|
644
733
|
const exerciseSlugsArray = exercises.map(exercise => exercise.slug);
|
645
734
|
const sidebar = await createInitialSidebar(exerciseSlugsArray);
|
735
|
+
await uploadFileToBucket(bucket, JSON.stringify(sidebar), `courses/${courseSlug}/.learn/sidebar.json`);
|
646
736
|
if (rigoToken) {
|
647
737
|
const { fixedSidebar } = await (0, sidebarGenerator_1.checkAndFixSidebarPure)(sidebar, exercises, rigoToken);
|
648
738
|
if (fixedSidebar) {
|
649
739
|
await uploadFileToBucket(bucket, JSON.stringify(fixedSidebar), `courses/${courseSlug}/.learn/sidebar.json`);
|
650
740
|
}
|
651
|
-
await uploadFileToBucket(bucket, JSON.stringify(sidebar), `courses/${courseSlug}/.learn/sidebar.json`);
|
652
741
|
return res.status(200).json(fixedSidebar);
|
653
742
|
}
|
654
|
-
await uploadFileToBucket(bucket, JSON.stringify(sidebar), `courses/${courseSlug}/.learn/sidebar.json`);
|
655
743
|
return res.status(200).json(sidebar);
|
656
744
|
}
|
657
745
|
console.error("Unexpected error:", error);
|
658
746
|
res.status(500).json({ error: error.message });
|
659
747
|
}
|
660
748
|
});
|
661
|
-
// app.get("/test/:slug", (req, res) => {
|
662
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
663
|
-
// lesson: "000-welcome-to-bird-domestication",
|
664
|
-
// status: "generating",
|
665
|
-
// log: "Hello",
|
666
|
-
// })
|
667
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
668
|
-
// lesson: "000-welcome-to-bird-domestication",
|
669
|
-
// status: "generating",
|
670
|
-
// log: "Hello",
|
671
|
-
// })
|
672
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
673
|
-
// lesson: "000-welcome-to-bird-domestication",
|
674
|
-
// status: "generating",
|
675
|
-
// log: "Hello broder",
|
676
|
-
// })
|
677
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
678
|
-
// lesson: "000-welcome-to-bird-domestication",
|
679
|
-
// status: "done",
|
680
|
-
// log: "Hello broder",
|
681
|
-
// })
|
682
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
683
|
-
// lesson: "other",
|
684
|
-
// status: "generating",
|
685
|
-
// log: "Hello",
|
686
|
-
// })
|
687
|
-
// res.send({ message: "Course creation started" })
|
688
|
-
// })
|
689
749
|
app.get("/technologies", async (req, res) => {
|
690
750
|
console.log("GET /technologies");
|
691
751
|
const technologies = await api_1.default.getCurrentTechnologies();
|
@@ -718,7 +778,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
718
778
|
if (!rigoToken || !bcToken) {
|
719
779
|
return res.status(400).json({ error: "Missing tokens" });
|
720
780
|
}
|
721
|
-
const courseSlug =
|
781
|
+
const courseSlug = syllabus.courseInfo.slug;
|
722
782
|
const tutorialDir = `courses/${courseSlug}`;
|
723
783
|
const learnJson = (0, exports.createLearnJson)(syllabus.courseInfo);
|
724
784
|
try {
|
@@ -755,9 +815,10 @@ class ServeCommand extends SessionCommand_1.default {
|
|
755
815
|
const firstLesson = syllabus.lessons[0];
|
756
816
|
const lastResult = "Nothing";
|
757
817
|
await startExerciseGeneration(bucket, rigoToken, syllabus.lessons, syllabus.courseInfo, firstLesson, tutorialDir, courseSlug, syllabus.courseInfo.purpose, lastResult);
|
818
|
+
await createInitialReadme(JSON.stringify(syllabus.courseInfo), courseSlug, rigoToken);
|
758
819
|
return res.json({
|
759
820
|
message: "Course created",
|
760
|
-
slug:
|
821
|
+
slug: syllabus.courseInfo.slug,
|
761
822
|
});
|
762
823
|
});
|
763
824
|
app.get("/courses/:courseSlug/syllabus", async (req, res) => {
|
@@ -873,11 +934,6 @@ class ServeCommand extends SessionCommand_1.default {
|
|
873
934
|
title = config.title[availableLangs[0]];
|
874
935
|
selectedLang = availableLangs[0];
|
875
936
|
}
|
876
|
-
console.log(config.description, "CONFIG DESCRIPTION");
|
877
|
-
// console.log(availableLangs, "AVAILABLE LANGs")
|
878
|
-
// console.log(selectedLang, "SELECTED LANG")
|
879
|
-
// console.log(title, "TITLE")
|
880
|
-
// 5) Inyectar placeholders en index.html
|
881
937
|
const idxTpl = fs.readFileSync(path.join(uiSrc, "index.html"), "utf-8");
|
882
938
|
const idxHtml = idxTpl
|
883
939
|
.replace(/{{title}}/g, title)
|
@@ -920,10 +976,11 @@ class ServeCommand extends SessionCommand_1.default {
|
|
920
976
|
form.append("file", fs.createReadStream(zipPath));
|
921
977
|
form.append("config", JSON.stringify(config));
|
922
978
|
const rigoRes = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/learnpack/upload`, form, {
|
923
|
-
headers: Object.assign(Object.assign({}, form.getHeaders()), { Authorization: `Token ${rigoToken}` }),
|
979
|
+
headers: Object.assign(Object.assign({}, form.getHeaders()), { Authorization: `Token ${rigoToken.trim()}` }),
|
924
980
|
});
|
925
|
-
await (
|
981
|
+
await createMultiLangAsset(bucket, rigoToken, bcToken, slug, fullConfig.config, rigoRes.data.url);
|
926
982
|
rimraf.sync(tmpRoot);
|
983
|
+
console.log("RigoRes", rigoRes.data);
|
927
984
|
return res.json({ url: rigoRes.data.url });
|
928
985
|
});
|
929
986
|
archive.on("error", err => {
|