@learnpack/learnpack 5.0.71 → 5.0.75

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.
Files changed (37) hide show
  1. package/README.md +13 -13
  2. package/lib/commands/publish.js +9 -6
  3. package/lib/commands/serve.js +48 -1
  4. package/lib/creatorDist/assets/{index-k_eF99Sf.css → index-BJ2JJzVC.css} +48 -12
  5. package/lib/creatorDist/assets/{index-Dm2fdeOs.js → index-CKBeex0S.js} +36853 -30578
  6. package/lib/creatorDist/index.html +2 -2
  7. package/lib/utils/api.js +18 -7
  8. package/lib/utils/creatorUtilities.d.ts +3 -0
  9. package/lib/utils/creatorUtilities.js +3 -0
  10. package/oclif.manifest.json +1 -1
  11. package/package.json +1 -1
  12. package/src/commands/init.ts +1 -0
  13. package/src/commands/publish.ts +13 -6
  14. package/src/commands/serve.ts +57 -1
  15. package/src/creator/package-lock.json +49 -0
  16. package/src/creator/package.json +1 -0
  17. package/src/creator/src/App.tsx +27 -21
  18. package/src/creator/src/components/ConsumablesManager.tsx +12 -2
  19. package/src/creator/src/components/LessonItem.tsx +3 -2
  20. package/src/creator/src/components/Loader.tsx +5 -1
  21. package/src/creator/src/components/Login.tsx +46 -135
  22. package/src/creator/src/components/syllabus/ContentIndex.tsx +84 -46
  23. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +55 -12
  24. package/src/creator/src/index.css +15 -0
  25. package/src/creator/src/utils/creatorUtils.ts +33 -3
  26. package/src/creator/src/utils/lib.ts +156 -2
  27. package/src/creator/src/utils/rigo.ts +3 -3
  28. package/src/creator/src/utils/store.ts +0 -1
  29. package/src/creatorDist/assets/{index-k_eF99Sf.css → index-BJ2JJzVC.css} +48 -12
  30. package/src/creatorDist/assets/{index-Dm2fdeOs.js → index-CKBeex0S.js} +36853 -30578
  31. package/src/creatorDist/index.html +2 -2
  32. package/src/ui/_app/app.css +1 -1
  33. package/src/ui/_app/app.js +529 -529
  34. package/src/ui/app.tar.gz +0 -0
  35. package/src/utils/api.ts +25 -7
  36. package/src/utils/creatorUtilities.ts +3 -0
  37. package/src/utils/creds.json +0 -13
@@ -1,5 +1,5 @@
1
1
  import axios from "axios"
2
- import { BREATHECODE_HOST } from "./constants"
2
+ import { BREATHECODE_HOST, RIGOBOT_HOST } from "./constants"
3
3
 
4
4
  type ParsedLesson = {
5
5
  id: string
@@ -26,7 +26,7 @@ export function parseLesson(input: string): ParsedLesson | null {
26
26
  }
27
27
  }
28
28
 
29
- // export const CREATOR_API_URL = "http://localhost:3000"
29
+ export const CREATOR_API_URL = "http://localhost:3000"
30
30
 
31
31
  export const uploadFileToBucket = async (content: string, path: string) => {
32
32
  const response = await axios.post(`/upload`, {
@@ -35,6 +35,13 @@ export const uploadFileToBucket = async (content: string, path: string) => {
35
35
  })
36
36
  return response.data
37
37
  }
38
+ export const uploadImageToBucket = async (imageUrl: string, path: string) => {
39
+ const response = await axios.post(`/upload-image`, {
40
+ image_url: imageUrl,
41
+ destination: path,
42
+ })
43
+ return response.data
44
+ }
38
45
 
39
46
  export const checkParams = () => {
40
47
  const urlParams = new URLSearchParams(window.location.search)
@@ -120,3 +127,150 @@ export const parseConsumables = (
120
127
 
121
128
  return result
122
129
  }
130
+
131
+ type LoginInfo = {
132
+ email: string
133
+ password: string
134
+ }
135
+
136
+ export const getRigobotJSON = async (breathecodeToken: string) => {
137
+ const rigoUrl = `${RIGOBOT_HOST}/v1/auth/me/token?breathecode_token=${breathecodeToken}`
138
+ const rigoResp = await fetch(rigoUrl)
139
+ if (!rigoResp.ok) {
140
+ throw new Error("Unable to obtain Rigobot token")
141
+ }
142
+ const rigobotJson = await rigoResp.json()
143
+ return rigobotJson
144
+ }
145
+ export const validateUser = async (breathecodeToken: string) => {
146
+ const config = {
147
+ method: "GET",
148
+ headers: {
149
+ "Content-Type": "application/json",
150
+ Authorization: `Token ${breathecodeToken}`,
151
+ },
152
+ }
153
+
154
+ const res = await fetch(`${BREATHECODE_HOST}/v1/auth/user/me`, config)
155
+ if (!res.ok) {
156
+ console.log("ERROR", res)
157
+ return null
158
+ }
159
+ const json = await res.json()
160
+
161
+ if ("roles" in json) {
162
+ delete json.roles
163
+ }
164
+ if ("permissions" in json) {
165
+ delete json.permissions
166
+ }
167
+ if ("settings" in json) {
168
+ delete json.settings
169
+ }
170
+
171
+ return json
172
+ }
173
+
174
+ export const login4Geeks = async (loginInfo: LoginInfo) => {
175
+ const url = `${BREATHECODE_HOST}/v1/auth/login/`
176
+
177
+ const res = await fetch(url, {
178
+ body: JSON.stringify(loginInfo),
179
+ method: "post",
180
+ headers: {
181
+ "Content-Type": "application/json",
182
+ },
183
+ })
184
+
185
+ if (!res.ok) {
186
+ throw Error("Unable to login with provided credentials")
187
+ }
188
+
189
+ const json = await res.json()
190
+
191
+ const rigoJson = await getRigobotJSON(json.token)
192
+
193
+ const user = await validateUser(json.token)
194
+ const returns = { ...json, rigobot: { ...rigoJson }, user }
195
+
196
+ return returns
197
+ }
198
+
199
+ export const loginWithToken = async (token: string) => {
200
+ const rigoJson = await getRigobotJSON(token)
201
+
202
+ const user = await validateUser(token)
203
+
204
+ const returns = { rigobot: { ...rigoJson }, ...user }
205
+
206
+ return returns
207
+ }
208
+
209
+ export const validateTokens = async (breathecodeToken: string) => {
210
+ const user = await validateUser(breathecodeToken)
211
+ console.log("USER", user)
212
+ if (!user) {
213
+ return false
214
+ }
215
+
216
+ const rigobotJson = await getRigobotJSON(breathecodeToken)
217
+ console.log("RIGOBOT", rigobotJson)
218
+
219
+ return true
220
+ }
221
+
222
+ export function extractImagesFromMarkdown(markdown: string) {
223
+ const imageRegex = /!\[([^\]]*)]\(([^)]+)\)/g
224
+ const images = []
225
+ let match
226
+
227
+ while ((match = imageRegex.exec(markdown)) !== null) {
228
+ const altText = match[1]
229
+ const url = match[2]
230
+ images.push({ alt: altText, url: url })
231
+ }
232
+
233
+ return images
234
+ }
235
+
236
+ export function getFilenameFromUrl(url: string): string {
237
+ try {
238
+ // 1) Use the URL constructor to strip off protocol/host/search/hash
239
+ const pathname = new URL(url, location.href).pathname
240
+ // 2) Grab everything after the last “/”
241
+ return pathname.substring(pathname.lastIndexOf("/") + 1)
242
+ } catch {
243
+ // Fallback for non-absolute URLs or invalid inputs
244
+ const clean = url.split("?")[0].split("#")[0]
245
+ return clean.substring(clean.lastIndexOf("/") + 1)
246
+ }
247
+ }
248
+
249
+ type TGenerateImageParams = {
250
+ prompt: string
251
+ }
252
+
253
+ export const generateImage = async (
254
+ token: string,
255
+ { prompt }: TGenerateImageParams
256
+ ) => {
257
+ try {
258
+ const response = await axios.post(
259
+ `${RIGOBOT_HOST}/v1/learnpack/tools/images`,
260
+ {
261
+ prompt,
262
+ },
263
+ {
264
+ headers: {
265
+ "Content-Type": "application/json",
266
+ Authorization: "Token " + token,
267
+ },
268
+ }
269
+ )
270
+
271
+ return response.data
272
+ } catch (error) {
273
+ console.error("Error generating image:", error)
274
+ return null
275
+ }
276
+ }
@@ -10,11 +10,11 @@ type TInteractiveCreationInputs = {
10
10
  prevInteractions: string
11
11
  }
12
12
  export const interactiveCreation = async (
13
- token: string,
13
+ // token: string,
14
14
  inputs: TInteractiveCreationInputs
15
15
  ) => {
16
16
  const response = await axios.post(
17
- `${RIGOBOT_HOST}/v1/prompting/completion/390/`,
17
+ `${RIGOBOT_HOST}/v1/prompting/public/completion/390/`,
18
18
  {
19
19
  inputs: inputs,
20
20
  include_purpose_objective: false,
@@ -23,7 +23,7 @@ export const interactiveCreation = async (
23
23
  {
24
24
  headers: {
25
25
  "Content-Type": "application/json",
26
- Authorization: "Token " + token,
26
+ // Authorization: "Token " + token,
27
27
  },
28
28
  }
29
29
  )
@@ -64,7 +64,6 @@ const useStore = create<Store>()(
64
64
  variables: [
65
65
  "description",
66
66
  "duration",
67
- "login",
68
67
  "targetAudience",
69
68
  "hasContentIndex",
70
69
  ],
@@ -57,7 +57,6 @@
57
57
  --color-red-300: oklch(80.8% 0.114 19.571);
58
58
  --color-red-500: oklch(63.7% 0.237 25.331);
59
59
  --color-red-700: oklch(50.5% 0.213 27.518);
60
- --color-yellow-50: oklch(98.7% 0.026 102.212);
61
60
  --color-sky-500: oklch(68.5% 0.169 237.323);
62
61
  --color-sky-600: oklch(58.8% 0.158 241.966);
63
62
  --color-blue-50: oklch(97% 0.014 254.604);
@@ -78,6 +77,7 @@
78
77
  --color-gray-700: oklch(37.3% 0.034 259.733);
79
78
  --color-gray-800: oklch(27.8% 0.033 256.848);
80
79
  --color-gray-900: oklch(21% 0.034 264.665);
80
+ --color-black: #000;
81
81
  --color-white: #fff;
82
82
  --spacing: 0.25rem;
83
83
  --container-sm: 24rem;
@@ -371,6 +371,9 @@
371
371
  .relative {
372
372
  position: relative;
373
373
  }
374
+ .inset-0 {
375
+ inset: calc(var(--spacing) * 0);
376
+ }
374
377
  .-top-1 {
375
378
  top: calc(var(--spacing) * -1);
376
379
  }
@@ -419,6 +422,9 @@
419
422
  .z-50 {
420
423
  z-index: 50;
421
424
  }
425
+ .z-1000 {
426
+ z-index: 1000;
427
+ }
422
428
  .container {
423
429
  width: 100%;
424
430
  }
@@ -453,9 +459,6 @@
453
459
  .mx-2 {
454
460
  margin-inline: calc(var(--spacing) * 2);
455
461
  }
456
- .mx-auto {
457
- margin-inline: auto;
458
- }
459
462
  .mt-1 {
460
463
  margin-top: calc(var(--spacing) * 1);
461
464
  }
@@ -468,9 +471,6 @@
468
471
  .mt-6 {
469
472
  margin-top: calc(var(--spacing) * 6);
470
473
  }
471
- .mt-10 {
472
- margin-top: calc(var(--spacing) * 10);
473
- }
474
474
  .mr-1 {
475
475
  margin-right: calc(var(--spacing) * 1);
476
476
  }
@@ -519,8 +519,8 @@
519
519
  .h-40 {
520
520
  height: calc(var(--spacing) * 40);
521
521
  }
522
- .h-50 {
523
- height: calc(var(--spacing) * 50);
522
+ .h-60 {
523
+ height: calc(var(--spacing) * 60);
524
524
  }
525
525
  .h-\[85\%\] {
526
526
  height: 85%;
@@ -537,6 +537,9 @@
537
537
  .max-h-\[300px\] {
538
538
  max-height: 300px;
539
539
  }
540
+ .min-h-\[70vh\] {
541
+ min-height: 70vh;
542
+ }
540
543
  .min-h-screen {
541
544
  min-height: 100vh;
542
545
  }
@@ -718,6 +721,18 @@
718
721
  .border-transparent {
719
722
  border-color: #0000;
720
723
  }
724
+ .bg-black\/50 {
725
+ background-color: #00000080;
726
+ }
727
+ @supports (color: color-mix(in lab, red, red)) {
728
+ .bg-black\/50 {
729
+ background-color: color-mix(
730
+ in oklab,
731
+ var(--color-black) 50%,
732
+ transparent
733
+ );
734
+ }
735
+ }
721
736
  .bg-blue-50 {
722
737
  background-color: var(--color-blue-50);
723
738
  }
@@ -745,9 +760,6 @@
745
760
  .bg-white {
746
761
  background-color: var(--color-white);
747
762
  }
748
- .bg-yellow-50 {
749
- background-color: var(--color-yellow-50);
750
- }
751
763
  .bg-gradient-to-t {
752
764
  --tw-gradient-position: to top in oklab;
753
765
  background-image: linear-gradient(var(--tw-gradient-stops));
@@ -906,6 +918,17 @@
906
918
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow),
907
919
  var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
908
920
  }
921
+ .transition {
922
+ transition-property: color, background-color, border-color, outline-color,
923
+ text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via,
924
+ --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate,
925
+ filter, -webkit-backdrop-filter, backdrop-filter;
926
+ transition-timing-function: var(
927
+ --tw-ease,
928
+ var(--default-transition-timing-function)
929
+ );
930
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
931
+ }
909
932
  .transition-all {
910
933
  transition-property: all;
911
934
  transition-timing-function: var(
@@ -1082,6 +1105,19 @@ h1 {
1082
1105
  .blue-on-hover:hover svg path {
1083
1106
  fill: var(--learnpack-blue);
1084
1107
  }
1108
+ .border-learnpack-blue {
1109
+ border-color: var(--learnpack-blue);
1110
+ }
1111
+ .red-ball {
1112
+ background-color: #eb5757;
1113
+ border: 2px solid #fff;
1114
+ border-radius: 50%;
1115
+ width: 16px;
1116
+ height: 16px;
1117
+ position: absolute;
1118
+ top: -10px;
1119
+ left: 10px;
1120
+ }
1085
1121
  @property --tw-translate-x {
1086
1122
  syntax: "*";
1087
1123
  inherits: false;