@learnpack/learnpack 5.0.288 → 5.0.291
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/serve.js +62 -76
- package/lib/creatorDist/assets/{index-BjO3hUuz.js → index-wLKEQIG6.js} +4470 -4491
- package/lib/creatorDist/index.html +1 -1
- package/lib/utils/configBuilder.js +20 -1
- package/lib/utils/export/index.d.ts +1 -0
- package/lib/utils/export/index.js +3 -1
- package/lib/utils/export/types.d.ts +1 -1
- package/lib/utils/export/zip.d.ts +2 -0
- package/lib/utils/export/zip.js +46 -0
- package/package.json +1 -1
- package/src/commands/serve.ts +75 -88
- package/src/creator/src/App.tsx +59 -43
- package/src/creator/src/components/syllabus/SyllabusEditor.tsx +1 -21
- package/src/creator/src/utils/lib.ts +468 -477
- package/src/creator/src/utils/store.ts +222 -223
- package/src/creatorDist/assets/{index-BjO3hUuz.js → index-wLKEQIG6.js} +4470 -4491
- package/src/creatorDist/index.html +1 -1
- package/src/ui/_app/app.js +397 -397
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/configBuilder.ts +100 -82
- package/src/utils/export/index.ts +1 -0
- package/src/utils/export/types.ts +1 -1
- package/src/utils/export/zip.ts +55 -0
- package/src/creator/src/components/PassphraseValidator.tsx +0 -47
@@ -10,7 +10,7 @@
|
|
10
10
|
/>
|
11
11
|
|
12
12
|
<title>Learnpack Creator: Craft tutorials in seconds!</title>
|
13
|
-
<script type="module" crossorigin src="/creator/assets/index-
|
13
|
+
<script type="module" crossorigin src="/creator/assets/index-wLKEQIG6.js"></script>
|
14
14
|
<link rel="stylesheet" crossorigin href="/creator/assets/index-C39zeF3W.css">
|
15
15
|
</head>
|
16
16
|
<body>
|
@@ -1,6 +1,23 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.buildConfig = buildConfig;
|
4
|
+
function naturalCompare(a, b) {
|
5
|
+
// Split by dots and hyphens, compare numbers as numbers
|
6
|
+
const regex = /(\d+|\D+)/g;
|
7
|
+
const ax = a.match(regex);
|
8
|
+
const bx = b.match(regex);
|
9
|
+
for (let i = 0; i < Math.max(ax.length, bx.length); i++) {
|
10
|
+
const an = parseInt(ax[i], 10);
|
11
|
+
const bn = parseInt(bx[i], 10);
|
12
|
+
if (!isNaN(an) && !isNaN(bn)) {
|
13
|
+
if (an !== bn)
|
14
|
+
return an - bn;
|
15
|
+
}
|
16
|
+
else if (ax[i] !== bx[i])
|
17
|
+
return (ax[i] || "").localeCompare(bx[i] || "");
|
18
|
+
}
|
19
|
+
return 0;
|
20
|
+
}
|
4
21
|
/**
|
5
22
|
* Crea la configuración y lista de ejercicios para un curso.
|
6
23
|
*
|
@@ -45,7 +62,9 @@ async function buildConfig(bucket, courseSlug) {
|
|
45
62
|
});
|
46
63
|
}
|
47
64
|
}
|
48
|
-
const exercises = Object.values(map)
|
65
|
+
const exercises = Object.values(map)
|
66
|
+
.sort((a, b) => naturalCompare(a.slug, b.slug))
|
67
|
+
.map((ex, i) => (Object.assign(Object.assign({}, ex), { position: i })));
|
49
68
|
return {
|
50
69
|
config: Object.assign({}, learnJson),
|
51
70
|
exercises,
|
@@ -1,7 +1,9 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.exportToEpub = exports.exportToScorm = void 0;
|
3
|
+
exports.exportToZip = exports.exportToEpub = exports.exportToScorm = void 0;
|
4
4
|
var scorm_1 = require("./scorm");
|
5
5
|
Object.defineProperty(exports, "exportToScorm", { enumerable: true, get: function () { return scorm_1.exportToScorm; } });
|
6
6
|
var epub_1 = require("./epub");
|
7
7
|
Object.defineProperty(exports, "exportToEpub", { enumerable: true, get: function () { return epub_1.exportToEpub; } });
|
8
|
+
var zip_1 = require("./zip");
|
9
|
+
Object.defineProperty(exports, "exportToZip", { enumerable: true, get: function () { return zip_1.exportToZip; } });
|
@@ -0,0 +1,46 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.exportToZip = exportToZip;
|
4
|
+
const path = require("path");
|
5
|
+
const fs = require("fs");
|
6
|
+
const archiver = require("archiver");
|
7
|
+
const mkdirp = require("mkdirp");
|
8
|
+
const rimraf = require("rimraf");
|
9
|
+
const uuid_1 = require("uuid");
|
10
|
+
const shared_1 = require("./shared");
|
11
|
+
async function exportToZip(options) {
|
12
|
+
const { courseSlug, bucket, outDir } = options;
|
13
|
+
// 1. Create temporary folder
|
14
|
+
const tmpName = (0, uuid_1.v4)();
|
15
|
+
const zipOutDir = path.join(outDir, tmpName);
|
16
|
+
rimraf.sync(zipOutDir);
|
17
|
+
mkdirp.sync(zipOutDir);
|
18
|
+
// 2. Download all course files from bucket to temporary directory
|
19
|
+
await (0, shared_1.downloadS3Folder)(bucket, `courses/${courseSlug}/`, zipOutDir);
|
20
|
+
// 3. Create ZIP file
|
21
|
+
const zipName = `${courseSlug}.zip`;
|
22
|
+
const zipPath = path.join(outDir, zipName);
|
23
|
+
// Remove existing zip file if it exists
|
24
|
+
if (fs.existsSync(zipPath)) {
|
25
|
+
fs.unlinkSync(zipPath);
|
26
|
+
}
|
27
|
+
const output = fs.createWriteStream(zipPath);
|
28
|
+
const archive = archiver("zip", { zlib: { level: 9 } });
|
29
|
+
return new Promise((resolve, reject) => {
|
30
|
+
output.on("close", () => {
|
31
|
+
console.log(`✅ ZIP export completed: ${archive.pointer()} total bytes`);
|
32
|
+
// Clean up temporary directory
|
33
|
+
rimraf.sync(zipOutDir);
|
34
|
+
resolve(zipPath);
|
35
|
+
});
|
36
|
+
archive.on("error", (err) => {
|
37
|
+
console.error("❌ ZIP creation error:", err);
|
38
|
+
rimraf.sync(zipOutDir);
|
39
|
+
reject(err);
|
40
|
+
});
|
41
|
+
archive.pipe(output);
|
42
|
+
// Add all files from the temporary directory to the ZIP
|
43
|
+
archive.directory(zipOutDir, false);
|
44
|
+
archive.finalize();
|
45
|
+
});
|
46
|
+
}
|
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.291",
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
6
6
|
"contributors": [
|
7
7
|
{
|
package/src/commands/serve.ts
CHANGED
@@ -56,7 +56,7 @@ import { checkReadability, slugify } from "../utils/creatorUtilities"
|
|
56
56
|
import { checkAndFixSidebarPure } from "../utils/sidebarGenerator"
|
57
57
|
import { handleAssetCreation } from "./publish"
|
58
58
|
import { FormState, Lesson, Syllabus } from "../models/creator"
|
59
|
-
import { exportToScorm, exportToEpub } from "../utils/export"
|
59
|
+
import { exportToScorm, exportToEpub, exportToZip } from "../utils/export"
|
60
60
|
|
61
61
|
const frontMatter = require("front-matter")
|
62
62
|
|
@@ -211,9 +211,17 @@ const createMultiLangAsset = async (
|
|
211
211
|
const indexReadme = await bucket.file(
|
212
212
|
`courses/${courseSlug}/README${getReadmeExtension(lang)}`
|
213
213
|
)
|
214
|
-
|
215
|
-
|
216
|
-
|
214
|
+
let indexReadmeString = ""
|
215
|
+
try {
|
216
|
+
// eslint-disable-next-line no-await-in-loop
|
217
|
+
const [indexReadmeContent] = await indexReadme.download()
|
218
|
+
indexReadmeString = indexReadmeContent.toString()
|
219
|
+
} catch (error) {
|
220
|
+
console.error("Error downloading index readme", error)
|
221
|
+
// TODO: Trigger generation of the index readme
|
222
|
+
indexReadmeString = ""
|
223
|
+
}
|
224
|
+
|
217
225
|
const b64IndexReadme = Buffer.from(indexReadmeString).toString("base64")
|
218
226
|
|
219
227
|
// eslint-disable-next-line no-await-in-loop
|
@@ -698,6 +706,7 @@ export default class ServeCommand extends SessionCommand {
|
|
698
706
|
}
|
699
707
|
)
|
700
708
|
|
709
|
+
// TODO: Check if this command is being used
|
701
710
|
app.post("/actions/generate-image/:courseSlug", async (req, res) => {
|
702
711
|
const rigoToken = req.header("x-rigo-token")
|
703
712
|
const { courseSlug } = req.params
|
@@ -1017,6 +1026,8 @@ export default class ServeCommand extends SessionCommand {
|
|
1017
1026
|
try {
|
1018
1027
|
console.log("GET CONFIG, COURSE SLUG", courseSlug)
|
1019
1028
|
const { config, exercises } = await buildConfig(bucket, courseSlug)
|
1029
|
+
console.log("CONFIG", config)
|
1030
|
+
console.log("EXERCISES", exercises)
|
1020
1031
|
res.set("X-Creator-Web", "true")
|
1021
1032
|
res.set("Access-Control-Expose-Headers", "X-Creator-Web")
|
1022
1033
|
|
@@ -1039,8 +1050,6 @@ export default class ServeCommand extends SessionCommand {
|
|
1039
1050
|
const courseSlug = req.query.slug
|
1040
1051
|
const lang = req.query.lang || "en"
|
1041
1052
|
|
1042
|
-
console.log("LANG", lang)
|
1043
|
-
|
1044
1053
|
if (!courseSlug) {
|
1045
1054
|
return res.status(400).json({ error: "Missing courseSlug" })
|
1046
1055
|
}
|
@@ -1574,53 +1583,6 @@ export default class ServeCommand extends SessionCommand {
|
|
1574
1583
|
}
|
1575
1584
|
})
|
1576
1585
|
|
1577
|
-
// app.post("/actions/continue-course/:courseSlug", async (req, res) => {
|
1578
|
-
// console.log("POST /actions/continue-course/:courseSlug")
|
1579
|
-
// const { courseSlug } = req.params
|
1580
|
-
|
1581
|
-
// const { feedback }: { feedback: string } = req.body
|
1582
|
-
|
1583
|
-
// const rigoToken = req.header("x-rigo-token")
|
1584
|
-
// const bcToken = req.header("x-breathecode-token")
|
1585
|
-
// if (!rigoToken || !bcToken) {
|
1586
|
-
// return res.status(400).json({ error: "Missing tokens" })
|
1587
|
-
// }
|
1588
|
-
|
1589
|
-
// const syllabus = await bucket.file(
|
1590
|
-
// `courses/${courseSlug}/.learn/initialSyllabus.json`
|
1591
|
-
// )
|
1592
|
-
// const [content] = await syllabus.download()
|
1593
|
-
// const syllabusJson: Syllabus = JSON.parse(content.toString())
|
1594
|
-
// const notGeneratedLessons = syllabusJson.lessons.filter(
|
1595
|
-
// lesson => !lesson.generated
|
1596
|
-
// )
|
1597
|
-
|
1598
|
-
// const lastGeneratedLesson = findLast(
|
1599
|
-
// syllabusJson.lessons,
|
1600
|
-
// lesson => lesson.generated ?? false
|
1601
|
-
// )
|
1602
|
-
|
1603
|
-
// console.log("ABout to generate", notGeneratedLessons.length, "lessons")
|
1604
|
-
|
1605
|
-
// const firstLessonToGenerate = notGeneratedLessons[0]
|
1606
|
-
|
1607
|
-
// const completionId = await startExerciseGeneration(
|
1608
|
-
// rigoToken,
|
1609
|
-
// syllabusJson.lessons,
|
1610
|
-
// syllabusJson.courseInfo,
|
1611
|
-
// firstLessonToGenerate,
|
1612
|
-
// courseSlug,
|
1613
|
-
// syllabusJson.courseInfo.purpose,
|
1614
|
-
// JSON.stringify(lastGeneratedLesson) +
|
1615
|
-
// `\n\nThe user provided this feedback in relation to the course: ${feedback}`
|
1616
|
-
// )
|
1617
|
-
|
1618
|
-
// return res.json({
|
1619
|
-
// message: "Course continued",
|
1620
|
-
// slug: courseSlug,
|
1621
|
-
// })
|
1622
|
-
// })
|
1623
|
-
|
1624
1586
|
app.get(
|
1625
1587
|
"/courses/:courseSlug/exercises/:exerciseSlug/",
|
1626
1588
|
async (req, res) => {
|
@@ -2048,47 +2010,72 @@ export default class ServeCommand extends SessionCommand {
|
|
2048
2010
|
let outputPath: string
|
2049
2011
|
let filename: string
|
2050
2012
|
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
2058
|
-
filename = `${course_slug}-scorm.zip`
|
2059
|
-
} else if (format === "epub") {
|
2060
|
-
console.log("EPUB export", metadata)
|
2061
|
-
// Validate required metadata for EPUB
|
2062
|
-
if (
|
2063
|
-
!metadata ||
|
2064
|
-
!metadata.creator ||
|
2065
|
-
!metadata.publisher ||
|
2066
|
-
!metadata.title ||
|
2067
|
-
!metadata.rights ||
|
2068
|
-
!metadata.lang
|
2069
|
-
) {
|
2070
|
-
console.log("Missing required metadata for EPUB export", metadata)
|
2071
|
-
return res.status(400).json({
|
2072
|
-
error: "Missing required metadata for EPUB export",
|
2073
|
-
required: ["creator", "publisher", "title", "rights", "lang"],
|
2013
|
+
switch (format) {
|
2014
|
+
case "scorm": {
|
2015
|
+
outputPath = await exportToScorm({
|
2016
|
+
courseSlug: course_slug,
|
2017
|
+
format: "scorm",
|
2018
|
+
bucket,
|
2019
|
+
outDir: path.join(__dirname, "../output/directory"),
|
2074
2020
|
})
|
2021
|
+
filename = `${course_slug}-scorm.zip`
|
2022
|
+
|
2023
|
+
break
|
2075
2024
|
}
|
2076
2025
|
|
2077
|
-
|
2078
|
-
{
|
2026
|
+
case "zip": {
|
2027
|
+
outputPath = await exportToZip({
|
2079
2028
|
courseSlug: course_slug,
|
2080
|
-
format: "
|
2029
|
+
format: "zip",
|
2081
2030
|
bucket,
|
2082
2031
|
outDir: path.join(__dirname, "../output/directory"),
|
2083
|
-
|
2084
|
-
}
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2032
|
+
})
|
2033
|
+
filename = `${course_slug}.zip`
|
2034
|
+
|
2035
|
+
break
|
2036
|
+
}
|
2037
|
+
|
2038
|
+
case "epub": {
|
2039
|
+
console.log("EPUB export", metadata)
|
2040
|
+
// Validate required metadata for EPUB
|
2041
|
+
if (
|
2042
|
+
!metadata ||
|
2043
|
+
!metadata.creator ||
|
2044
|
+
!metadata.publisher ||
|
2045
|
+
!metadata.title ||
|
2046
|
+
!metadata.rights ||
|
2047
|
+
!metadata.lang
|
2048
|
+
) {
|
2049
|
+
console.log(
|
2050
|
+
"Missing required metadata for EPUB export",
|
2051
|
+
metadata
|
2052
|
+
)
|
2053
|
+
return res.status(400).json({
|
2054
|
+
error: "Missing required metadata for EPUB export",
|
2055
|
+
required: ["creator", "publisher", "title", "rights", "lang"],
|
2056
|
+
})
|
2057
|
+
}
|
2058
|
+
|
2059
|
+
outputPath = await exportToEpub(
|
2060
|
+
{
|
2061
|
+
courseSlug: course_slug,
|
2062
|
+
format: "epub",
|
2063
|
+
bucket,
|
2064
|
+
outDir: path.join(__dirname, "../output/directory"),
|
2065
|
+
language: language,
|
2066
|
+
},
|
2067
|
+
metadata
|
2068
|
+
)
|
2069
|
+
filename = `${course_slug}.epub`
|
2070
|
+
|
2071
|
+
break
|
2072
|
+
}
|
2073
|
+
|
2074
|
+
default: {
|
2075
|
+
return res.status(400).json({
|
2076
|
+
error: "Invalid format. Supported formats: scorm, epub, zip",
|
2077
|
+
})
|
2078
|
+
}
|
2092
2079
|
}
|
2093
2080
|
|
2094
2081
|
// Send the file and clean up
|
package/src/creator/src/App.tsx
CHANGED
@@ -6,7 +6,7 @@ import { useNavigate } from "react-router"
|
|
6
6
|
import { useShallow } from "zustand/react/shallow"
|
7
7
|
import useStore, { TDifficulty } from "./utils/store"
|
8
8
|
|
9
|
-
import { publicInteractiveCreation } from "./utils/rigo"
|
9
|
+
import { publicInteractiveCreation, isHuman } from "./utils/rigo"
|
10
10
|
import {
|
11
11
|
checkParams,
|
12
12
|
isValidRigoToken,
|
@@ -21,8 +21,8 @@ import {
|
|
21
21
|
import { Uploader } from "./components/Uploader"
|
22
22
|
import toast from "react-hot-toast"
|
23
23
|
import { ParamsChecker } from "./components/ParamsChecker"
|
24
|
-
import { RIGO_FLOAT_GIF } from "./utils/constants"
|
25
|
-
|
24
|
+
import { DEV_MODE, RIGO_FLOAT_GIF } from "./utils/constants"
|
25
|
+
import TurnstileChallenge from "./components/TurnstileChallenge"
|
26
26
|
// import TurnstileChallenge from "./components/TurnstileChallenge"
|
27
27
|
import ResumeCourseModal from "./components/ResumeCourseModal"
|
28
28
|
import { possiblePurposes, PurposeSelector } from "./components/PurposeSelector"
|
@@ -31,7 +31,6 @@ 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 PassphraseValidator from "./components/PassphraseValidator"
|
35
34
|
|
36
35
|
function App() {
|
37
36
|
const navigate = useNavigate()
|
@@ -86,22 +85,6 @@ function App() {
|
|
86
85
|
checkTechs()
|
87
86
|
}, [])
|
88
87
|
|
89
|
-
const tokenVerification = async () => {
|
90
|
-
const isValid = await isValidPublicToken(auth.publicToken)
|
91
|
-
if (!isValid) {
|
92
|
-
setAuth({
|
93
|
-
...auth,
|
94
|
-
publicToken: ""
|
95
|
-
})
|
96
|
-
}
|
97
|
-
}
|
98
|
-
|
99
|
-
useEffect(() => {
|
100
|
-
if (auth.publicToken) {
|
101
|
-
tokenVerification()
|
102
|
-
}
|
103
|
-
}, [auth])
|
104
|
-
|
105
88
|
const verifyToken = async () => {
|
106
89
|
const { token } = checkParams(["token"])
|
107
90
|
if (token) {
|
@@ -147,9 +130,12 @@ function App() {
|
|
147
130
|
if (duration && !isNaN(parseInt(duration))) {
|
148
131
|
if (["30", "60", "120"].includes(duration)) {
|
149
132
|
const durationInt = parseInt(duration)
|
133
|
+
console.log("duration", durationInt)
|
150
134
|
setFormState({
|
151
135
|
duration: durationInt,
|
152
136
|
})
|
137
|
+
} else {
|
138
|
+
console.log("Invalid duration received in params", duration)
|
153
139
|
}
|
154
140
|
}
|
155
141
|
|
@@ -215,13 +201,13 @@ function App() {
|
|
215
201
|
}
|
216
202
|
}
|
217
203
|
|
218
|
-
if (auth.publicToken) {
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
204
|
+
if (auth.publicToken && !isAuthenticated) {
|
205
|
+
const isPublicTokenValid = await isValidPublicToken(auth.publicToken)
|
206
|
+
if (isPublicTokenValid) {
|
207
|
+
tokenToUse = auth.publicToken
|
208
|
+
isAuthenticated = true
|
209
|
+
tokenType = "public"
|
210
|
+
}
|
225
211
|
}
|
226
212
|
if (!isAuthenticated) {
|
227
213
|
setShowTurnstileModal(true)
|
@@ -327,7 +313,7 @@ function App() {
|
|
327
313
|
onClick={() => {
|
328
314
|
setFormState({
|
329
315
|
duration: 30,
|
330
|
-
currentStep: "
|
316
|
+
currentStep: "verifyHuman",
|
331
317
|
})
|
332
318
|
}}
|
333
319
|
selected={formState.duration === 30}
|
@@ -338,7 +324,7 @@ function App() {
|
|
338
324
|
onClick={() => {
|
339
325
|
setFormState({
|
340
326
|
duration: 60,
|
341
|
-
currentStep: "
|
327
|
+
currentStep: "verifyHuman",
|
342
328
|
})
|
343
329
|
}}
|
344
330
|
selected={formState.duration === 60}
|
@@ -349,7 +335,7 @@ function App() {
|
|
349
335
|
onClick={() => {
|
350
336
|
setFormState({
|
351
337
|
duration: 120,
|
352
|
-
currentStep: "
|
338
|
+
currentStep: "verifyHuman",
|
353
339
|
})
|
354
340
|
}}
|
355
341
|
selected={formState.duration === 120}
|
@@ -358,20 +344,52 @@ function App() {
|
|
358
344
|
),
|
359
345
|
},
|
360
346
|
{
|
361
|
-
title: t("stepWizard.
|
362
|
-
slug: "
|
347
|
+
title: t("stepWizard.verifyHuman"),
|
348
|
+
slug: "verifyHuman",
|
363
349
|
isCompleted: false,
|
350
|
+
required: true,
|
364
351
|
content: (
|
365
|
-
|
366
|
-
{
|
367
|
-
|
368
|
-
|
352
|
+
<TurnstileChallenge
|
353
|
+
siteKey={
|
354
|
+
DEV_MODE ? "0x4AAAAAABeKMBYYinMU4Ib0" : "0x4AAAAAABeZ9tjEevGBsJFU"
|
355
|
+
}
|
356
|
+
onSuccess={async (token) => {
|
357
|
+
const { human, message, token: jwtToken } = await isHuman(token)
|
358
|
+
if (human) {
|
359
|
+
toast.success(t("stepWizard.humanSuccess"))
|
360
|
+
|
361
|
+
console.log("JWT TOKEN received", jwtToken)
|
369
362
|
setAuth({
|
370
363
|
...auth,
|
371
|
-
publicToken:
|
364
|
+
publicToken: jwtToken,
|
372
365
|
})
|
373
|
-
|
374
|
-
|
366
|
+
setFormState({
|
367
|
+
currentStep: "hasContentIndex",
|
368
|
+
})
|
369
|
+
} else {
|
370
|
+
toast.error(message)
|
371
|
+
setFormState({
|
372
|
+
currentStep: "duration",
|
373
|
+
})
|
374
|
+
}
|
375
|
+
}}
|
376
|
+
onError={() => {
|
377
|
+
toast.error(t("turnstileModal.error"), {
|
378
|
+
duration: 10000,
|
379
|
+
})
|
380
|
+
setFormState({
|
381
|
+
currentStep: "duration",
|
382
|
+
})
|
383
|
+
}}
|
384
|
+
/>
|
385
|
+
),
|
386
|
+
},
|
387
|
+
{
|
388
|
+
title: t("stepWizard.hasContentIndex"),
|
389
|
+
slug: "hasContentIndex",
|
390
|
+
isCompleted: false,
|
391
|
+
content: (
|
392
|
+
<>
|
375
393
|
<div className="flex flex-col md:flex-row gap-2 justify-center">
|
376
394
|
<SelectableCard
|
377
395
|
title={t("stepWizard.hasContentIndexCard.no")}
|
@@ -386,7 +404,7 @@ function App() {
|
|
386
404
|
isCompleted: true,
|
387
405
|
})
|
388
406
|
}}
|
389
|
-
|
407
|
+
// selected={formState.hasContentIndex === false}
|
390
408
|
/>
|
391
409
|
<SelectableCard
|
392
410
|
title={t("stepWizard.hasContentIndexCard.yes")}
|
@@ -397,7 +415,7 @@ function App() {
|
|
397
415
|
variables: [...formState.variables, "contentIndex"],
|
398
416
|
})
|
399
417
|
}}
|
400
|
-
|
418
|
+
// selected={formState.hasContentIndex === true}
|
401
419
|
/>
|
402
420
|
</div>
|
403
421
|
</>
|
@@ -466,11 +484,9 @@ function App() {
|
|
466
484
|
|
467
485
|
push({
|
468
486
|
lessons,
|
469
|
-
generationMode: "continue-with-all",
|
470
487
|
courseInfo: {
|
471
488
|
...formState,
|
472
489
|
title: res.parsed.title,
|
473
|
-
|
474
490
|
slug: slugify(fixTitleLength(res.parsed.title)),
|
475
491
|
description: res.parsed.description,
|
476
492
|
language:
|
@@ -14,7 +14,6 @@ import {
|
|
14
14
|
useConsumableCall,
|
15
15
|
isValidRigoToken,
|
16
16
|
isValidPublicToken,
|
17
|
-
getMyPackages,
|
18
17
|
} from "../../utils/lib"
|
19
18
|
|
20
19
|
import Loader from "../Loader"
|
@@ -75,7 +74,7 @@ const SyllabusEditor: React.FC = () => {
|
|
75
74
|
}, [syllabus, navigate])
|
76
75
|
|
77
76
|
useEffect(() => {
|
78
|
-
;
|
77
|
+
;(async () => {
|
79
78
|
const { token } = checkParams(["token"])
|
80
79
|
if (token) {
|
81
80
|
const user = await loginWithToken(token)
|
@@ -93,25 +92,6 @@ const SyllabusEditor: React.FC = () => {
|
|
93
92
|
checkSlug()
|
94
93
|
}, [])
|
95
94
|
|
96
|
-
|
97
|
-
const checkMyPackages = async () => {
|
98
|
-
if (auth.rigoToken) {
|
99
|
-
const packages = await getMyPackages(auth.rigoToken)
|
100
|
-
if (Array.isArray(packages) && packages.length === 0) {
|
101
|
-
push({
|
102
|
-
...syllabus,
|
103
|
-
generationMode: "continue-with-all",
|
104
|
-
})
|
105
|
-
}
|
106
|
-
}
|
107
|
-
}
|
108
|
-
|
109
|
-
useEffect(() => {
|
110
|
-
if (auth.rigoToken) {
|
111
|
-
checkMyPackages()
|
112
|
-
}
|
113
|
-
}, [auth])
|
114
|
-
|
115
95
|
const checkSlug = async () => {
|
116
96
|
if (!syllabus.courseInfo.title) {
|
117
97
|
toast.error("Please provide a title for the course")
|