@learnpack/learnpack 5.0.191 → 5.0.198

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.
@@ -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-CXaPa6wN.js"></script>
13
+ <script type="module" crossorigin src="/creator/assets/index-DszesaEz.js"></script>
14
14
  <link rel="stylesheet" crossorigin href="/creator/assets/index-Bnq3eZ3T.css">
15
15
  </head>
16
16
  <body>
@@ -1 +1 @@
1
- {"version":"5.0.191","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":[]}}}
1
+ {"version":"5.0.198","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.191",
4
+ "version": "5.0.198",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -220,8 +220,7 @@ export async function processExercise(
220
220
  purposeSlug
221
221
  )
222
222
 
223
- if (!reducedReadme)
224
- break
223
+ if (!reducedReadme) break
225
224
 
226
225
  readability = checkReadability(
227
226
  reducedReadme.parsed.content,
@@ -345,14 +344,6 @@ export default class ServeCommand extends SessionCommand {
345
344
  process.exit(1)
346
345
  }
347
346
 
348
- let deploymentURL = process.env.DEPLOYMENT_URL
349
- if (!deploymentURL) {
350
- console.log("DEPLOYMENT_URL is not set, using default value")
351
- deploymentURL = "https://app.learnpack.co"
352
- }
353
-
354
- console.log("DEPLOYMENT_URL", deploymentURL)
355
-
356
347
  const credentials = JSON.parse(crendsEnv)
357
348
  const bucketStorage = new Storage({
358
349
  credentials,
@@ -7,7 +7,12 @@ import { useShallow } from "zustand/react/shallow"
7
7
  import useStore from "./utils/store"
8
8
 
9
9
  import { publicInteractiveCreation, isHuman } from "./utils/rigo"
10
- import { checkParams, loginWithToken, parseLesson } from "./utils/lib"
10
+ import {
11
+ checkParams,
12
+ isValidRigoToken,
13
+ loginWithToken,
14
+ parseLesson,
15
+ } from "./utils/lib"
11
16
 
12
17
  import { Uploader } from "./components/Uploader"
13
18
  import toast from "react-hot-toast"
@@ -32,6 +37,8 @@ function App() {
32
37
  uploadedFiles,
33
38
  auth,
34
39
  resetFormState,
40
+ cleanAll,
41
+ setMessages,
35
42
  } = useStore(
36
43
  useShallow((state) => ({
37
44
  formState: state.formState,
@@ -44,6 +51,8 @@ function App() {
44
51
  uploadedFiles: state.uploadedFiles,
45
52
  auth: state.auth,
46
53
  resetFormState: state.resetFormState,
54
+ cleanAll: state.cleanAll,
55
+ setMessages: state.setMessages,
47
56
  }))
48
57
  )
49
58
 
@@ -115,16 +124,25 @@ function App() {
115
124
 
116
125
  const handleCreateTutorial = async () => {
117
126
  try {
118
- cleanHistory()
127
+ const isValid = await isValidRigoToken(auth.rigoToken)
128
+ if (!isValid) {
129
+ setAuth({
130
+ ...auth,
131
+ rigoToken: "",
132
+ bcToken: "",
133
+ userId: "",
134
+ user: null,
135
+ })
136
+ }
119
137
 
120
138
  const res = await publicInteractiveCreation(
121
139
  {
122
140
  courseInfo: `${JSON.stringify(formState)} `,
123
141
  prevInteractions: "",
124
142
  },
125
- auth.rigoToken ? auth.rigoToken : auth.publicToken,
143
+ auth.rigoToken && isValid ? auth.rigoToken : auth.publicToken,
126
144
  formState.purpose || "learnpack-lesson-writer",
127
- auth.rigoToken ? false : true
145
+ auth.rigoToken && isValid ? false : true
128
146
  )
129
147
  const lessons = res.parsed.listOfSteps.map((lesson: any) => {
130
148
  return parseLesson(lesson, [])
@@ -138,19 +156,32 @@ function App() {
138
156
  title: res.parsed.title,
139
157
  description: res.parsed.description,
140
158
  },
141
- messages: [
142
- {
143
- type: "assistant",
144
- content: res.parsed.aiMessage,
145
- },
146
- ],
147
- // sources: uploadedFiles,
159
+ // messages: [],
148
160
  })
149
161
  navigate("/creator/syllabus")
150
162
  setFormState({
151
163
  isCompleted: false,
152
164
  currentStep: "description",
153
165
  })
166
+ setMessages([
167
+ {
168
+ type: "user",
169
+ content: formState.description,
170
+ },
171
+ {
172
+ type: "assistant",
173
+ content: res.parsed.aiMessage,
174
+ },
175
+ {
176
+ type: "assistant",
177
+ content: "If you're satisfied, type 'OK' in the chat.",
178
+ },
179
+ {
180
+ type: "assistant",
181
+ content:
182
+ "If not, what would you like me to change? You can sat things like:\n - Add more exercises\n - Make it more difficult\n - Remove step 1.1 and replace it with a new step that explains the concept of X ",
183
+ },
184
+ ])
154
185
  } catch (error) {
155
186
  console.error(error, "ERROR CREATING TUTORIAL")
156
187
  toast.error("Something went wrong. Please try again.")
@@ -246,6 +277,7 @@ function App() {
246
277
  title: "Please verify you are a human",
247
278
  slug: "verifyHuman",
248
279
  isCompleted: false,
280
+ required: true,
249
281
  content: (
250
282
  <TurnstileChallenge
251
283
  siteKey={
@@ -356,6 +388,7 @@ function App() {
356
388
  }}
357
389
  onStartOver={() => {
358
390
  resetFormState()
391
+ cleanAll()
359
392
  cleanHistory()
360
393
  }}
361
394
  />
@@ -1,11 +1,11 @@
1
1
  import { SVGS } from "../assets/svgs"
2
- import { UploadedFile } from "../utils/store"
2
+ import { ParsedFile } from "./FileUploader"
3
3
 
4
4
  export const FileCard = ({
5
5
  file,
6
6
  handleRemove,
7
7
  }: {
8
- file: UploadedFile
8
+ file: ParsedFile
9
9
  handleRemove: () => void
10
10
  }) => (
11
11
  <div className="flex items-center justify-between bg-white shadow-sm p-2 rounded-lg w-[100px]">
@@ -1,17 +1,16 @@
1
1
  import { useEffect, useRef, useState } from "react"
2
2
  import useStore from "../../utils/store"
3
- import { TMessage } from "../Message"
4
3
  import FileUploader from "../FileUploader"
5
4
  import { SVGS } from "../../assets/svgs"
6
5
  import { Message } from "../Message"
7
6
  import { FileCard } from "../FileCard"
8
7
 
9
8
  export const Sidebar = ({
10
- messages,
9
+ // messages,
11
10
  sendPrompt,
12
11
  handleSubmit,
13
12
  }: {
14
- messages: TMessage[]
13
+ // messages: TMessage[]
15
14
  sendPrompt: (prompt: string) => void
16
15
  handleSubmit: () => void
17
16
  }) => {
@@ -19,6 +18,7 @@ export const Sidebar = ({
19
18
  const inputRef = useRef<HTMLTextAreaElement>(null)
20
19
  const uploadedFiles = useStore((state) => state.uploadedFiles)
21
20
  const setUploadedFiles = useStore((state) => state.setUploadedFiles)
21
+ const messages = useStore((state) => state.messages)
22
22
  const [showBubble, setShowBubble] = useState(true)
23
23
 
24
24
  const [isOpen, setIsOpen] = useState(false)
@@ -110,7 +110,6 @@ export const Sidebar = ({
110
110
  style={{ resize: "none" }}
111
111
  className="w-full h-full p-2 outline-blue rounded"
112
112
  placeholder="How can Learnpack help you?"
113
- autoFocus
114
113
  onKeyUp={(e) => {
115
114
  if (e.key === "Enter" && !e.shiftKey) {
116
115
  e.preventDefault()
@@ -11,6 +11,8 @@ import {
11
11
  createCourse,
12
12
  isSlugAvailable,
13
13
  reWriteTitle,
14
+ useConsumableCall,
15
+ isValidRigoToken,
14
16
  } from "../../utils/lib"
15
17
 
16
18
  import Loader from "../Loader"
@@ -29,37 +31,20 @@ import { RIGO_FLOAT_GIF } from "../../utils/constants"
29
31
  const SyllabusEditor: React.FC = () => {
30
32
  const navigate = useNavigate()
31
33
 
32
- const {
33
- history,
34
- auth,
35
- setAuth,
36
- push,
37
- // uploadedFiles,
38
- cleanHistory,
39
- formState,
40
- } = useStore(
41
- useShallow((state) => ({
42
- history: state.history,
43
- auth: state.auth,
44
- setAuth: state.setAuth,
45
- push: state.push,
46
- // uploadedFiles: state.uploadedFiles,
47
- cleanHistory: state.cleanHistory,
48
- formState: state.formState,
49
- }))
50
- )
34
+ const { history, auth, setAuth, push, cleanAll, messages, setMessages } =
35
+ useStore(
36
+ useShallow((state) => ({
37
+ history: state.history,
38
+ auth: state.auth,
39
+ setAuth: state.setAuth,
40
+ push: state.push,
41
+ cleanAll: state.cleanAll,
42
+ messages: state.messages,
43
+ // formState: state.formState,
44
+ setMessages: state.setMessages,
45
+ }))
46
+ )
51
47
 
52
- const [messages, setMessages] = useState<TMessage[]>([
53
- {
54
- type: "assistant",
55
- content: "If you're satisfied, type 'OK' in the chat.",
56
- },
57
- {
58
- type: "assistant",
59
- content:
60
- "If not, what would you like me to change? You can sat things like:\n - Add more exercises\n - Make it more difficult\n - Remove step 1.1 and replace it with a new step that explains the concept of X ",
61
- },
62
- ])
63
48
  const [isGenerating, setIsGenerating] = useState(false)
64
49
  const [showLoginModal, setShowLoginModal] = useState(false)
65
50
  const [isThinking, setIsThinking] = useState(false)
@@ -72,26 +57,6 @@ const SyllabusEditor: React.FC = () => {
72
57
  }
73
58
  }, [syllabus, navigate])
74
59
 
75
- useEffect(() => {
76
- console.log(formState.description, "DESCRIPTION")
77
-
78
- if (formState.description) {
79
- setMessages((prevMessages) => {
80
- if (prevMessages.length === 0 || prevMessages[0].type !== "user") {
81
- // Si no hay mensajes o el primero no es de usuario, lo agrego al inicio
82
- return [
83
- { type: "user", content: formState.description },
84
- ...prevMessages,
85
- ]
86
- } else {
87
- // Si el primero ya es de usuario, lo reemplazo y mantengo el resto
88
- const [, ...rest] = prevMessages
89
- return [{ type: "user", content: formState.description }, ...rest]
90
- }
91
- })
92
- }
93
- }, [formState.description])
94
-
95
60
  useEffect(() => {
96
61
  ;(async () => {
97
62
  const { token } = checkParams(["token"])
@@ -139,6 +104,17 @@ const SyllabusEditor: React.FC = () => {
139
104
  { type: "assistant", content: "" },
140
105
  ])
141
106
 
107
+ const isValid = await isValidRigoToken(auth.rigoToken)
108
+ if (!isValid) {
109
+ setAuth({
110
+ ...auth,
111
+ rigoToken: "",
112
+ bcToken: "",
113
+ userId: "",
114
+ user: null,
115
+ })
116
+ }
117
+
142
118
  const res = await publicInteractiveCreation(
143
119
  {
144
120
  courseInfo: JSON.stringify(syllabus.courseInfo),
@@ -147,9 +123,9 @@ const SyllabusEditor: React.FC = () => {
147
123
  .map((message) => `${message.type}: ${message.content}`)
148
124
  .join("\n") + `\nUSER: ${prompt}`,
149
125
  },
150
- auth.rigoToken ? auth.rigoToken : auth.publicToken,
126
+ auth.rigoToken && isValid ? auth.rigoToken : auth.publicToken,
151
127
  syllabus?.courseInfo?.purpose || "learnpack-lesson-writer",
152
- auth.rigoToken ? false : true
128
+ auth.rigoToken && isValid ? false : true
153
129
  )
154
130
 
155
131
  const lessons: Lesson[] = res.parsed.listOfSteps.map((step: any) =>
@@ -165,20 +141,25 @@ const SyllabusEditor: React.FC = () => {
165
141
  res.parsed.description || syllabus.courseInfo.description,
166
142
  },
167
143
  })
168
- setMessages((prev) => {
169
- const newMessages = [...prev]
170
- newMessages[newMessages.length - 1].content = res.parsed.aiMessage
171
- return newMessages
172
- })
144
+ const newMessages: TMessage[] = [
145
+ ...messages,
146
+ {
147
+ type: "user",
148
+ content: prompt,
149
+ },
150
+ {
151
+ type: "assistant",
152
+ content: res.parsed.aiMessage,
153
+ },
154
+ ]
155
+ setMessages(newMessages)
173
156
  setIsThinking(false)
174
157
  } catch (error) {
175
158
  console.error(error)
176
159
  // Remove the last message
177
- setMessages((prev) => {
178
- const newMessages = [...prev]
179
- newMessages.pop()
180
- return newMessages
181
- })
160
+ const newMessages = [...messages]
161
+ newMessages.pop()
162
+ setMessages(newMessages as TMessage[])
182
163
  setIsThinking(false)
183
164
  }
184
165
  }
@@ -207,22 +188,28 @@ const SyllabusEditor: React.FC = () => {
207
188
  setShowLoginModal(true)
208
189
  return
209
190
  }
210
- // const success = await useConsumableCall(
211
- // auth.bcToken,
212
- // "ai-course-generation"
213
- // )
214
- // if (!success) {
215
- // toast.error("You don't have enough credits to generate a course!")
216
- // return
217
- // }
218
- // syllabus.sources = uploadedFiles
219
- console.log(syllabus)
191
+ const success = await useConsumableCall(
192
+ auth.bcToken,
193
+ "ai-course-generation"
194
+ )
195
+ if (!success) {
196
+ toast.error(
197
+ "You don't have enough credits to generate a course! Please add more credits to your account."
198
+ )
199
+ toast.error("You will be redirected to the settings page in 5 seconds.")
200
+ setTimeout(() => {
201
+ window.location.href =
202
+ "https://learnpack.co/settings?token=" + auth.bcToken
203
+ }, 5000)
204
+ return
205
+ }
206
+ console.log(syllabus, "SYLLABUS")
220
207
 
221
208
  setIsGenerating(true)
222
209
  createCourse(syllabus, tokenToUse, auth.bcToken)
223
210
 
224
211
  setTimeout(() => {
225
- cleanHistory()
212
+ cleanAll()
226
213
  setIsGenerating(false)
227
214
  window.location.href = `/preview/${slugify(
228
215
  syllabus.courseInfo.title || ""
@@ -256,7 +243,7 @@ It may take a moment..."
256
243
  <ConsumablesManager />
257
244
 
258
245
  <Sidebar
259
- messages={messages}
246
+ // messages={messages}
260
247
  sendPrompt={sendPrompt}
261
248
  handleSubmit={handleSubmit}
262
249
  />
@@ -3,8 +3,12 @@ import { generateImage, getFilenameFromUrl, uploadImageToBucket } from "./lib"
3
3
 
4
4
  export const slugify = (text: string) => {
5
5
  return text
6
+ .toString()
7
+ .normalize("NFD")
8
+ .replace(/[\u0300-\u036F]/g, "")
6
9
  .toLowerCase()
7
- .replace(/ /g, "-")
10
+ .trim()
11
+ .replace(/\s+/g, "-")
8
12
  .replace(/[^\w.-]+/g, "")
9
13
  }
10
14
 
@@ -102,7 +102,6 @@ export async function useConsumableCall(
102
102
  const response = await axios.put(url, {}, { headers })
103
103
 
104
104
  if (response.status >= 200 && response.status < 300) {
105
- console.log(response.data)
106
105
  console.log(`Successfully consumed ${consumableSlug}`)
107
106
  return true
108
107
  } else {
@@ -417,3 +416,13 @@ export async function registerUserWithFormData(
417
416
  }
418
417
  }
419
418
  }
419
+
420
+ export const isValidRigoToken = async (rigobotToken: string) => {
421
+ const rigoUrl = `${RIGOBOT_HOST}/v1/auth/token/${rigobotToken}`
422
+ const rigoResp = await fetch(rigoUrl)
423
+ if (!rigoResp.ok) {
424
+ return false
425
+ }
426
+
427
+ return true
428
+ }
@@ -30,17 +30,13 @@ type Auth = {
30
30
  export type Syllabus = {
31
31
  lessons: Lesson[]
32
32
  courseInfo: FormState
33
- messages: TMessage[]
33
+ // messages: TMessage[]
34
34
  }
35
35
 
36
36
  type Consumables = {
37
37
  [key: string]: number
38
38
  }
39
39
 
40
- export type UploadedFile = {
41
- name: string
42
- text: string
43
- }
44
40
  type Store = {
45
41
  auth: Auth
46
42
  formState: FormState
@@ -52,11 +48,13 @@ type Store = {
52
48
  setPlanToRedirect: (planToRedirect: string) => void
53
49
  uploadedFiles: ParsedFile[]
54
50
  setUploadedFiles: (uploadedFiles: ParsedFile[]) => void
55
-
51
+ messages: TMessage[]
52
+ setMessages: (messages: TMessage[]) => void
56
53
  cleanHistory: () => void
57
54
  history: Syllabus[]
58
55
  undo: () => void
59
56
  push: (syllabus: Syllabus) => void
57
+ cleanAll: () => void
60
58
  // setSyllabus: (syllabus: Partial<Syllabus>) => void
61
59
  consumables: Consumables
62
60
  setConsumables: (consumables: Partial<Consumables>) => void
@@ -94,6 +92,8 @@ const useStore = create<Store>()(
94
92
  "verifyHuman",
95
93
  ],
96
94
  },
95
+ messages: [],
96
+ setMessages: (messages: TMessage[]) => set({ messages }),
97
97
  setFormState: (formState: Partial<FormState>) =>
98
98
  set((state) => ({ formState: { ...state.formState, ...formState } })),
99
99
  resetFormState: () =>
@@ -139,6 +139,30 @@ const useStore = create<Store>()(
139
139
  cleanHistory: () => {
140
140
  set(() => ({ history: [] }))
141
141
  },
142
+ cleanAll: () => {
143
+ set({
144
+ uploadedFiles: [],
145
+ messages: [],
146
+ history: [],
147
+ formState: {
148
+ description: "",
149
+ duration: 0,
150
+ targetAudience: "",
151
+ hasContentIndex: false,
152
+ contentIndex: "",
153
+ purpose: "",
154
+ isCompleted: false,
155
+ variables: [
156
+ "description",
157
+ "duration",
158
+ "purpose",
159
+ "hasContentIndex",
160
+ "verifyHuman",
161
+ ],
162
+ currentStep: "description",
163
+ },
164
+ })
165
+ },
142
166
  consumables: {},
143
167
  setConsumables: (consumables: Partial<Consumables>) =>
144
168
  set((state) => {