@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/src/commands/serve.ts
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import { flags } from "@oclif/command"
|
2
2
|
|
3
|
-
// import { readDocument } from "../utils/readDocuments"
|
4
3
|
import { YoutubeTranscript } from "youtube-transcript"
|
5
4
|
import * as express from "express"
|
6
5
|
import * as cors from "cors"
|
@@ -30,6 +29,8 @@ import {
|
|
30
29
|
// makeReadmeReadable,
|
31
30
|
generateImage,
|
32
31
|
isPackageAuthor,
|
32
|
+
createStructuredPreviewReadme,
|
33
|
+
translateCourseMetadata,
|
33
34
|
} from "../utils/rigoActions"
|
34
35
|
import * as dotenv from "dotenv"
|
35
36
|
import {
|
@@ -64,15 +65,13 @@ function findLast<T>(
|
|
64
65
|
export const createLearnJson = (courseInfo: FormState) => {
|
65
66
|
// console.log("courseInfo to create learn json", courseInfo)
|
66
67
|
|
67
|
-
const expectedPreviewUrl = `https://${
|
68
|
-
courseInfo.title as string
|
69
|
-
)}.learn-pack.com/preview.png`
|
68
|
+
const expectedPreviewUrl = `https://${courseInfo.slug}.learn-pack.com/preview.png`
|
70
69
|
console.log("Preview url in generated learn.json", expectedPreviewUrl)
|
71
70
|
|
72
71
|
const language = courseInfo.language || "en"
|
73
72
|
|
74
73
|
const learnJson = {
|
75
|
-
slug:
|
74
|
+
slug: courseInfo.slug,
|
76
75
|
title:
|
77
76
|
language === "en" || language === "us" ?
|
78
77
|
{
|
@@ -105,27 +104,6 @@ const uploadFileToBucket = async (
|
|
105
104
|
await fileRef.save(Buffer.from(file, "utf8"))
|
106
105
|
}
|
107
106
|
|
108
|
-
const uploadImageToBucket = async (
|
109
|
-
bucket: Bucket,
|
110
|
-
url: string,
|
111
|
-
path: string
|
112
|
-
) => {
|
113
|
-
const response = await fetch(url)
|
114
|
-
if (!response.ok) {
|
115
|
-
throw new Error(`Failed to download image: ${response.statusText}`)
|
116
|
-
}
|
117
|
-
|
118
|
-
const contentType =
|
119
|
-
response.headers.get("content-type") || "application/octet-stream"
|
120
|
-
const buffer = await response.arrayBuffer()
|
121
|
-
|
122
|
-
const fileRef = bucket.file(path)
|
123
|
-
await fileRef.save(Buffer.from(buffer), {
|
124
|
-
resumable: false,
|
125
|
-
contentType,
|
126
|
-
})
|
127
|
-
}
|
128
|
-
|
129
107
|
const PARAMS = {
|
130
108
|
expected_grade_level: "8",
|
131
109
|
max_fkgl: 10,
|
@@ -135,25 +113,23 @@ const PARAMS = {
|
|
135
113
|
}
|
136
114
|
|
137
115
|
export const processImage = async (
|
138
|
-
bucket: Bucket,
|
139
|
-
tutorialDir: string,
|
140
116
|
url: string,
|
141
117
|
description: string,
|
142
|
-
rigoToken: string
|
118
|
+
rigoToken: string,
|
119
|
+
courseSlug: string
|
143
120
|
) => {
|
144
121
|
try {
|
145
122
|
// TODO: MAKE THIS ASYNC
|
146
123
|
const filename = getFilenameFromUrl(url)
|
147
124
|
|
148
|
-
|
149
|
-
const imagePath = `${tutorialDir}/.learn/assets/${filename}`
|
150
|
-
|
151
|
-
console.log("🖼️ Generating image", imagePath)
|
125
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${courseSlug}/images/${filename}`
|
152
126
|
|
153
|
-
|
154
|
-
|
127
|
+
await generateImage(rigoToken, {
|
128
|
+
prompt: description,
|
129
|
+
callbackUrl: webhookUrl,
|
130
|
+
})
|
155
131
|
|
156
|
-
console.log("✅ Image", imagePath, "generated successfully!")
|
132
|
+
// console.log("✅ Image", imagePath, "generated successfully!")
|
157
133
|
return true
|
158
134
|
} catch {
|
159
135
|
return false
|
@@ -201,7 +177,6 @@ const uploadInitialReadme = async (
|
|
201
177
|
}
|
202
178
|
|
203
179
|
const cleanFormState = (formState: FormState) => {
|
204
|
-
// keysToDelete: description, technologies, purpose
|
205
180
|
const {
|
206
181
|
description,
|
207
182
|
technologies,
|
@@ -217,6 +192,51 @@ const cleanFormState = (formState: FormState) => {
|
|
217
192
|
return rest
|
218
193
|
}
|
219
194
|
|
195
|
+
const createMultiLangAsset = async (
|
196
|
+
bucket: Bucket,
|
197
|
+
rigoToken: string,
|
198
|
+
bcToken: string,
|
199
|
+
courseSlug: string,
|
200
|
+
courseJson: any,
|
201
|
+
deployUrl: string
|
202
|
+
) => {
|
203
|
+
const availableLangs = Object.keys(courseJson.title)
|
204
|
+
console.log("AVAILABLE LANGUAGES to upload asset", availableLangs)
|
205
|
+
|
206
|
+
const all_translations: string[] = []
|
207
|
+
|
208
|
+
for (const lang of availableLangs) {
|
209
|
+
// eslint-disable-next-line no-await-in-loop
|
210
|
+
const indexReadme = await bucket.file(
|
211
|
+
`courses/${courseSlug}/README.${
|
212
|
+
lang === "us" || lang === "en" ? "md" : `${lang}.md`
|
213
|
+
}`
|
214
|
+
)
|
215
|
+
// eslint-disable-next-line no-await-in-loop
|
216
|
+
const [indexReadmeContent] = await indexReadme.download()
|
217
|
+
const indexReadmeString = indexReadmeContent.toString()
|
218
|
+
const b64IndexReadme = Buffer.from(indexReadmeString).toString("base64")
|
219
|
+
|
220
|
+
// eslint-disable-next-line no-await-in-loop
|
221
|
+
const asset = await handleAssetCreation(
|
222
|
+
{ token: bcToken, rigobotToken: rigoToken },
|
223
|
+
courseJson,
|
224
|
+
lang,
|
225
|
+
deployUrl,
|
226
|
+
b64IndexReadme,
|
227
|
+
all_translations
|
228
|
+
)
|
229
|
+
|
230
|
+
all_translations.push(asset.slug)
|
231
|
+
}
|
232
|
+
// const languageCodes = new Set(languageCodes)
|
233
|
+
// const asset = await api.createAsset(rigoToken, {
|
234
|
+
// slug: courseSlug,
|
235
|
+
// title: courseJson.title,
|
236
|
+
// description: courseJson.description,
|
237
|
+
// })
|
238
|
+
}
|
239
|
+
|
220
240
|
async function startExerciseGeneration(
|
221
241
|
bucket: Bucket,
|
222
242
|
rigoToken: string,
|
@@ -253,6 +273,27 @@ async function startExerciseGeneration(
|
|
253
273
|
)
|
254
274
|
}
|
255
275
|
|
276
|
+
async function createInitialReadme(
|
277
|
+
tutorialInfo: string,
|
278
|
+
tutorialSlug: string,
|
279
|
+
rigoToken: string
|
280
|
+
) {
|
281
|
+
const webhookUrl = `${process.env.HOST}/webhooks/${tutorialSlug}/initial-readme-processor`
|
282
|
+
console.log("Creating initial readme", webhookUrl)
|
283
|
+
try {
|
284
|
+
const res = await createStructuredPreviewReadme(
|
285
|
+
rigoToken,
|
286
|
+
{
|
287
|
+
tutorial_info: tutorialInfo,
|
288
|
+
},
|
289
|
+
webhookUrl
|
290
|
+
)
|
291
|
+
console.log("Initial readme created", res)
|
292
|
+
} catch (error) {
|
293
|
+
console.error("Error creating initial readme", error)
|
294
|
+
}
|
295
|
+
}
|
296
|
+
|
256
297
|
const fixPreviewUrl = (slug: string, previewUrl: string) => {
|
257
298
|
if (!previewUrl) {
|
258
299
|
return null
|
@@ -482,6 +523,27 @@ export default class ServeCommand extends SessionCommand {
|
|
482
523
|
res.json({ id, status: "SUCCESS" })
|
483
524
|
})
|
484
525
|
|
526
|
+
app.post(
|
527
|
+
"/webhooks/:courseSlug/initial-readme-processor",
|
528
|
+
async (req, res) => {
|
529
|
+
const { courseSlug } = req.params
|
530
|
+
const body = req.body
|
531
|
+
|
532
|
+
// Save the file as courses/courseSlug/README.md
|
533
|
+
const filePath = `courses/${courseSlug}/README.${
|
534
|
+
body.parsed.language_code === "us" ||
|
535
|
+
body.parsed.language_code === "en" ?
|
536
|
+
"md" :
|
537
|
+
`${body.parsed.language_code}.md`
|
538
|
+
}`
|
539
|
+
console.log("Saving initial readme to", filePath)
|
540
|
+
await uploadFileToBucket(bucket, body.parsed.content, filePath)
|
541
|
+
console.log("Initial readme saved to", filePath)
|
542
|
+
|
543
|
+
res.json({ status: "SUCCESS" })
|
544
|
+
}
|
545
|
+
)
|
546
|
+
|
485
547
|
app.post("/webhooks/:courseSlug/images/:imageId", async (req, res) => {
|
486
548
|
const { courseSlug, imageId } = req.params
|
487
549
|
const body = req.body
|
@@ -629,13 +691,7 @@ export default class ServeCommand extends SessionCommand {
|
|
629
691
|
})
|
630
692
|
for (const image of imagesArray) {
|
631
693
|
// eslint-disable-next-line no-await-in-loop
|
632
|
-
await processImage(
|
633
|
-
bucket,
|
634
|
-
`courses/${courseSlug}`,
|
635
|
-
image.url,
|
636
|
-
image.alt,
|
637
|
-
rigoToken
|
638
|
-
)
|
694
|
+
await processImage(image.url, image.alt, rigoToken, courseSlug)
|
639
695
|
}
|
640
696
|
}
|
641
697
|
|
@@ -863,25 +919,34 @@ export default class ServeCommand extends SessionCommand {
|
|
863
919
|
|
864
920
|
app.post("/actions/translate", express.json(), async (req, res) => {
|
865
921
|
console.log("POST /actions/translate")
|
866
|
-
const { exerciseSlugs, languages, rigoToken } = req.body
|
922
|
+
const { exerciseSlugs, languages, rigoToken, currentLanguage } = req.body
|
867
923
|
const query = req.query
|
868
924
|
const courseSlug = query.slug
|
869
925
|
|
870
|
-
console.log("EXERCISE SLUGS", exerciseSlugs)
|
871
|
-
console.log("LANGUAGES", languages)
|
872
|
-
console.log("RIGO TOKEN", rigoToken)
|
873
|
-
|
874
926
|
if (!rigoToken) {
|
875
927
|
return res.status(400).json({ error: "RigoToken not found" })
|
876
928
|
}
|
877
929
|
|
878
930
|
const languagesToTranslate: string[] = languages.split(",")
|
879
931
|
|
932
|
+
const course = await bucket
|
933
|
+
.file(`courses/${courseSlug}/learn.json`)
|
934
|
+
.download()
|
935
|
+
|
936
|
+
const courseJson = JSON.parse(course.toString())
|
937
|
+
const languageCodes = new Set()
|
938
|
+
|
880
939
|
try {
|
881
940
|
await Promise.all(
|
882
941
|
exerciseSlugs.map(async (slug: string) => {
|
883
|
-
const readmePath = `courses/${courseSlug}/exercises/${slug}/README
|
942
|
+
const readmePath = `courses/${courseSlug}/exercises/${slug}/README${
|
943
|
+
currentLanguage === "us" || currentLanguage === "en" ?
|
944
|
+
"" :
|
945
|
+
`.${currentLanguage}`
|
946
|
+
}.md`
|
947
|
+
|
884
948
|
const readme = await bucket.file(readmePath).download()
|
949
|
+
|
885
950
|
await Promise.all(
|
886
951
|
languagesToTranslate.map(async (language: string) => {
|
887
952
|
const response = await translateExercise(rigoToken, {
|
@@ -891,14 +956,98 @@ export default class ServeCommand extends SessionCommand {
|
|
891
956
|
})
|
892
957
|
|
893
958
|
const translatedReadme = await bucket.file(
|
894
|
-
`courses/${courseSlug}/exercises/${slug}/README
|
959
|
+
`courses/${courseSlug}/exercises/${slug}/README${
|
960
|
+
response.parsed.output_language_code === "us" ||
|
961
|
+
response.parsed.output_language_code === "en" ?
|
962
|
+
"" :
|
963
|
+
`.${response.parsed.output_language_code}`
|
964
|
+
}.md`
|
895
965
|
)
|
896
966
|
await translatedReadme.save(response.parsed.translation)
|
967
|
+
|
968
|
+
languageCodes.add(response.parsed.output_language_code)
|
897
969
|
})
|
898
970
|
)
|
899
971
|
})
|
900
972
|
)
|
901
973
|
|
974
|
+
if (languageCodes.has("en")) {
|
975
|
+
languageCodes.delete("en")
|
976
|
+
languageCodes.add("us")
|
977
|
+
}
|
978
|
+
|
979
|
+
const currentLanguages = Object.keys(courseJson.title)
|
980
|
+
for (const languageCode of currentLanguages) {
|
981
|
+
if (languageCodes.has(languageCode)) {
|
982
|
+
languageCodes.delete(languageCode)
|
983
|
+
}
|
984
|
+
}
|
985
|
+
|
986
|
+
if ([...languageCodes].length > 0) {
|
987
|
+
console.log("TRANSLATING COURSE METADATA", languageCodes)
|
988
|
+
|
989
|
+
const translatedCourseMetadata = await Promise.all(
|
990
|
+
[...languageCodes].map(async languageCode => {
|
991
|
+
const result = await translateCourseMetadata(rigoToken, {
|
992
|
+
title: courseJson.title[currentLanguage],
|
993
|
+
description: courseJson.description[currentLanguage],
|
994
|
+
destination_lang_code: languageCode as string,
|
995
|
+
})
|
996
|
+
|
997
|
+
return {
|
998
|
+
languageCode,
|
999
|
+
title: result.parsed.title,
|
1000
|
+
description: result.parsed.description,
|
1001
|
+
}
|
1002
|
+
})
|
1003
|
+
)
|
1004
|
+
|
1005
|
+
for (const metadata of translatedCourseMetadata) {
|
1006
|
+
courseJson.title[metadata.languageCode as string] = metadata.title
|
1007
|
+
courseJson.description[metadata.languageCode as string] =
|
1008
|
+
metadata.description
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
await uploadFileToBucket(
|
1012
|
+
bucket,
|
1013
|
+
JSON.stringify(courseJson),
|
1014
|
+
`courses/${courseSlug}/learn.json`
|
1015
|
+
)
|
1016
|
+
|
1017
|
+
const previewReadme = await bucket.file(
|
1018
|
+
`courses/${courseSlug}/README${
|
1019
|
+
currentLanguage === "us" || currentLanguage === "en" ?
|
1020
|
+
"" :
|
1021
|
+
`.${currentLanguage}`
|
1022
|
+
}.md`
|
1023
|
+
)
|
1024
|
+
const [previewReadmeContent] = await previewReadme.download()
|
1025
|
+
const previewReadmeContentString = previewReadmeContent.toString()
|
1026
|
+
|
1027
|
+
await Promise.all(
|
1028
|
+
[...languageCodes].map(async languageCode => {
|
1029
|
+
const translatedPreviewReadme = await translateExercise(
|
1030
|
+
rigoToken,
|
1031
|
+
{
|
1032
|
+
text_to_translate: previewReadmeContentString,
|
1033
|
+
output_language: languageCode as string,
|
1034
|
+
exercise_slug: "preview-readme",
|
1035
|
+
}
|
1036
|
+
)
|
1037
|
+
|
1038
|
+
await bucket
|
1039
|
+
.file(
|
1040
|
+
`courses/${courseSlug}/README${
|
1041
|
+
languageCode === "us" || languageCode === "en" ?
|
1042
|
+
"" :
|
1043
|
+
`.${languageCode}`
|
1044
|
+
}.md`
|
1045
|
+
)
|
1046
|
+
.save(translatedPreviewReadme.parsed.translation)
|
1047
|
+
})
|
1048
|
+
)
|
1049
|
+
}
|
1050
|
+
|
902
1051
|
return res.status(200).json({ message: "Translated exercises" })
|
903
1052
|
} catch (error) {
|
904
1053
|
console.log(error, "ERROR")
|
@@ -907,6 +1056,8 @@ export default class ServeCommand extends SessionCommand {
|
|
907
1056
|
})
|
908
1057
|
|
909
1058
|
app.delete("/exercise/:slug/delete", async (req, res) => {
|
1059
|
+
console.log("DELETE /exercise/:slug/delete")
|
1060
|
+
|
910
1061
|
const { slug } = req.params
|
911
1062
|
const query = req.query
|
912
1063
|
const courseSlug = query.slug
|
@@ -960,13 +1111,17 @@ export default class ServeCommand extends SessionCommand {
|
|
960
1111
|
res.json(sidebar)
|
961
1112
|
} catch (error: any) {
|
962
1113
|
if (error.code === 404) {
|
963
|
-
console.log("SIDEBAR FILE NOT FOUND", courseSlug)
|
964
|
-
|
965
1114
|
const { exercises } = await buildConfig(bucket, courseSlug)
|
966
1115
|
|
967
1116
|
const exerciseSlugsArray = exercises.map(exercise => exercise.slug)
|
968
1117
|
const sidebar = await createInitialSidebar(exerciseSlugsArray)
|
969
1118
|
|
1119
|
+
await uploadFileToBucket(
|
1120
|
+
bucket,
|
1121
|
+
JSON.stringify(sidebar),
|
1122
|
+
`courses/${courseSlug}/.learn/sidebar.json`
|
1123
|
+
)
|
1124
|
+
|
970
1125
|
if (rigoToken) {
|
971
1126
|
const { fixedSidebar } = await checkAndFixSidebarPure(
|
972
1127
|
sidebar,
|
@@ -981,20 +1136,9 @@ export default class ServeCommand extends SessionCommand {
|
|
981
1136
|
)
|
982
1137
|
}
|
983
1138
|
|
984
|
-
await uploadFileToBucket(
|
985
|
-
bucket,
|
986
|
-
JSON.stringify(sidebar),
|
987
|
-
`courses/${courseSlug}/.learn/sidebar.json`
|
988
|
-
)
|
989
1139
|
return res.status(200).json(fixedSidebar)
|
990
1140
|
}
|
991
1141
|
|
992
|
-
await uploadFileToBucket(
|
993
|
-
bucket,
|
994
|
-
JSON.stringify(sidebar),
|
995
|
-
`courses/${courseSlug}/.learn/sidebar.json`
|
996
|
-
)
|
997
|
-
|
998
1142
|
return res.status(200).json(sidebar)
|
999
1143
|
}
|
1000
1144
|
|
@@ -1003,35 +1147,6 @@ export default class ServeCommand extends SessionCommand {
|
|
1003
1147
|
}
|
1004
1148
|
})
|
1005
1149
|
|
1006
|
-
// app.get("/test/:slug", (req, res) => {
|
1007
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
1008
|
-
// lesson: "000-welcome-to-bird-domestication",
|
1009
|
-
// status: "generating",
|
1010
|
-
// log: "Hello",
|
1011
|
-
// })
|
1012
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
1013
|
-
// lesson: "000-welcome-to-bird-domestication",
|
1014
|
-
// status: "generating",
|
1015
|
-
// log: "Hello",
|
1016
|
-
// })
|
1017
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
1018
|
-
// lesson: "000-welcome-to-bird-domestication",
|
1019
|
-
// status: "generating",
|
1020
|
-
// log: "Hello broder",
|
1021
|
-
// })
|
1022
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
1023
|
-
// lesson: "000-welcome-to-bird-domestication",
|
1024
|
-
// status: "done",
|
1025
|
-
// log: "Hello broder",
|
1026
|
-
// })
|
1027
|
-
// emitToCourse(req.params.slug, "course-creation", {
|
1028
|
-
// lesson: "other",
|
1029
|
-
// status: "generating",
|
1030
|
-
// log: "Hello",
|
1031
|
-
// })
|
1032
|
-
// res.send({ message: "Course creation started" })
|
1033
|
-
// })
|
1034
|
-
|
1035
1150
|
app.get("/technologies", async (req, res) => {
|
1036
1151
|
console.log("GET /technologies")
|
1037
1152
|
|
@@ -1071,7 +1186,7 @@ export default class ServeCommand extends SessionCommand {
|
|
1071
1186
|
return res.status(400).json({ error: "Missing tokens" })
|
1072
1187
|
}
|
1073
1188
|
|
1074
|
-
const courseSlug =
|
1189
|
+
const courseSlug = syllabus.courseInfo.slug
|
1075
1190
|
|
1076
1191
|
const tutorialDir = `courses/${courseSlug}`
|
1077
1192
|
const learnJson = createLearnJson(syllabus.courseInfo)
|
@@ -1161,9 +1276,15 @@ export default class ServeCommand extends SessionCommand {
|
|
1161
1276
|
lastResult
|
1162
1277
|
)
|
1163
1278
|
|
1279
|
+
await createInitialReadme(
|
1280
|
+
JSON.stringify(syllabus.courseInfo),
|
1281
|
+
courseSlug,
|
1282
|
+
rigoToken
|
1283
|
+
)
|
1284
|
+
|
1164
1285
|
return res.json({
|
1165
1286
|
message: "Course created",
|
1166
|
-
slug:
|
1287
|
+
slug: syllabus.courseInfo.slug,
|
1167
1288
|
})
|
1168
1289
|
})
|
1169
1290
|
|
@@ -1331,12 +1452,6 @@ export default class ServeCommand extends SessionCommand {
|
|
1331
1452
|
selectedLang = availableLangs[0]
|
1332
1453
|
}
|
1333
1454
|
|
1334
|
-
console.log(config.description, "CONFIG DESCRIPTION")
|
1335
|
-
// console.log(availableLangs, "AVAILABLE LANGs")
|
1336
|
-
// console.log(selectedLang, "SELECTED LANG")
|
1337
|
-
// console.log(title, "TITLE")
|
1338
|
-
|
1339
|
-
// 5) Inyectar placeholders en index.html
|
1340
1455
|
const idxTpl = fs.readFileSync(path.join(uiSrc, "index.html"), "utf-8")
|
1341
1456
|
const idxHtml = idxTpl
|
1342
1457
|
.replace(/{{title}}/g, title)
|
@@ -1403,20 +1518,22 @@ export default class ServeCommand extends SessionCommand {
|
|
1403
1518
|
{
|
1404
1519
|
headers: {
|
1405
1520
|
...form.getHeaders(),
|
1406
|
-
Authorization: `Token ${rigoToken}`,
|
1521
|
+
Authorization: `Token ${rigoToken.trim()}`,
|
1407
1522
|
},
|
1408
1523
|
}
|
1409
1524
|
)
|
1410
1525
|
|
1411
|
-
await
|
1412
|
-
|
1526
|
+
await createMultiLangAsset(
|
1527
|
+
bucket,
|
1528
|
+
rigoToken,
|
1529
|
+
bcToken,
|
1530
|
+
slug,
|
1413
1531
|
fullConfig.config,
|
1414
|
-
selectedLang,
|
1415
1532
|
rigoRes.data.url
|
1416
1533
|
)
|
1417
1534
|
|
1418
1535
|
rimraf.sync(tmpRoot)
|
1419
|
-
|
1536
|
+
console.log("RigoRes", rigoRes.data)
|
1420
1537
|
return res.json({ url: rigoRes.data.url })
|
1421
1538
|
})
|
1422
1539
|
|
package/src/creator/src/App.tsx
CHANGED
@@ -26,6 +26,7 @@ import ResumeCourseModal from "./components/ResumeCourseModal"
|
|
26
26
|
import { possiblePurposes, PurposeSelector } from "./components/PurposeSelector"
|
27
27
|
import { useTranslation } from "react-i18next"
|
28
28
|
import NotificationListener from "./components/NotificationListener"
|
29
|
+
import { slugify } from "./utils/creatorUtils"
|
29
30
|
|
30
31
|
function App() {
|
31
32
|
const navigate = useNavigate()
|
@@ -410,7 +411,8 @@ function App() {
|
|
410
411
|
lessons,
|
411
412
|
courseInfo: {
|
412
413
|
...formState,
|
413
|
-
title:
|
414
|
+
title: res.parsed.title,
|
415
|
+
slug: slugify(fixTitleLength(res.parsed.title)),
|
414
416
|
description: res.parsed.description,
|
415
417
|
language:
|
416
418
|
res.parsed.languageCode || formState.language || "en",
|
@@ -13,7 +13,6 @@ import {
|
|
13
13
|
// reWriteTitle,
|
14
14
|
useConsumableCall,
|
15
15
|
isValidRigoToken,
|
16
|
-
fixTitleLength,
|
17
16
|
} from "../../utils/lib"
|
18
17
|
|
19
18
|
import Loader from "../Loader"
|
@@ -96,25 +95,23 @@ const SyllabusEditor: React.FC = () => {
|
|
96
95
|
return
|
97
96
|
}
|
98
97
|
|
99
|
-
let
|
100
|
-
let
|
101
|
-
let isAvailable = await isSlugAvailable(slug)
|
98
|
+
let newSlug = syllabus.courseInfo.slug
|
99
|
+
let isAvailable = await isSlugAvailable(syllabus.courseInfo.slug)
|
102
100
|
|
103
101
|
while (!isAvailable) {
|
104
|
-
if (
|
105
|
-
|
102
|
+
if (newSlug.length > 50) {
|
103
|
+
newSlug = newSlug.slice(0, 44)
|
106
104
|
}
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
isAvailable = await isSlugAvailable(slug)
|
105
|
+
newSlug = newSlug + "-" + randomUUID()
|
106
|
+
newSlug = newSlug.slice(0, 50)
|
107
|
+
isAvailable = await isSlugAvailable(newSlug)
|
111
108
|
}
|
112
109
|
|
113
110
|
push({
|
114
111
|
...syllabus,
|
115
112
|
courseInfo: {
|
116
113
|
...syllabus.courseInfo,
|
117
|
-
|
114
|
+
slug: newSlug,
|
118
115
|
},
|
119
116
|
})
|
120
117
|
}
|
@@ -230,6 +227,8 @@ const SyllabusEditor: React.FC = () => {
|
|
230
227
|
|
231
228
|
if (!syllabus) return null
|
232
229
|
|
230
|
+
console.log(syllabus.courseInfo)
|
231
|
+
|
233
232
|
return isGenerating ? (
|
234
233
|
<>
|
235
234
|
<Loader
|
@@ -253,8 +252,7 @@ It may take a moment..."
|
|
253
252
|
lessons: lessons,
|
254
253
|
courseInfo: {
|
255
254
|
...syllabus.courseInfo,
|
256
|
-
title:
|
257
|
-
fixTitleLength(res.parsed.title) || syllabus.courseInfo.title,
|
255
|
+
title: res.parsed.title || syllabus.courseInfo.title,
|
258
256
|
description:
|
259
257
|
res.parsed.description || syllabus.courseInfo.description,
|
260
258
|
language:
|
@@ -15,12 +15,14 @@ export const publicInteractiveCreation = async (
|
|
15
15
|
publicRequest: boolean = true
|
16
16
|
): Promise<any | null> => {
|
17
17
|
try {
|
18
|
-
const randomUID = randomUUID(
|
18
|
+
const randomUID = randomUUID(15)
|
19
19
|
const webhookUrl = `${
|
20
20
|
DEV_MODE
|
21
21
|
? "https://9cw5zmww-3000.use2.devtunnels.ms"
|
22
22
|
: window.location.origin
|
23
|
+
// "https://9cw5zmww-3000.use2.devtunnels.ms"
|
23
24
|
}/notifications/${randomUID}`
|
25
|
+
|
24
26
|
const response = await axios.post(
|
25
27
|
`${RIGOBOT_HOST}/v1/prompting${
|
26
28
|
publicRequest ? "/public" : ""
|
@@ -42,7 +44,7 @@ export const publicInteractiveCreation = async (
|
|
42
44
|
return { res: response.data, notificationId: randomUID }
|
43
45
|
} catch (error: unknown) {
|
44
46
|
const err = error as AxiosError
|
45
|
-
console.log("error", err)
|
47
|
+
console.log("error trying to create course", err)
|
46
48
|
|
47
49
|
if (err.response?.status === 403) {
|
48
50
|
toast.error("You've reached the limit. Please log in to continue.")
|
@@ -11,6 +11,7 @@ export type FormState = {
|
|
11
11
|
hasContentIndex: boolean
|
12
12
|
contentIndex: string
|
13
13
|
purpose: string
|
14
|
+
slug: string
|
14
15
|
language?: string
|
15
16
|
isCompleted: boolean
|
16
17
|
variables: string[]
|
@@ -85,6 +86,7 @@ const useStore = create<Store>()(
|
|
85
86
|
formState: {
|
86
87
|
description: "",
|
87
88
|
duration: 0,
|
89
|
+
slug: "",
|
88
90
|
hasContentIndex: false,
|
89
91
|
contentIndex: "",
|
90
92
|
purpose: "",
|
@@ -119,6 +121,7 @@ const useStore = create<Store>()(
|
|
119
121
|
resetFormState: () =>
|
120
122
|
set({
|
121
123
|
formState: {
|
124
|
+
slug: "",
|
122
125
|
currentStep: "description",
|
123
126
|
description: "",
|
124
127
|
duration: 0,
|
@@ -169,7 +172,7 @@ const useStore = create<Store>()(
|
|
169
172
|
formState: {
|
170
173
|
description: "",
|
171
174
|
duration: 0,
|
172
|
-
|
175
|
+
slug: "",
|
173
176
|
language: "en",
|
174
177
|
technologies: [],
|
175
178
|
hasContentIndex: false,
|