@learnpack/learnpack 5.0.308 → 5.0.309
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/package.json +1 -1
- package/src/creator/src/utils/lib.ts +172 -172
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.309",
|
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
|
6
6
|
"contributors": [
|
|
7
7
|
{
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import axios from "axios"
|
|
2
|
-
import { franc } from "franc"
|
|
3
|
-
import { BREATHECODE_HOST, DEV_MODE, RIGOBOT_HOST } from "./constants"
|
|
4
|
-
import { Lesson } from "../components/LessonItem"
|
|
5
|
-
import { randomUUID } from "./creatorUtils"
|
|
6
|
-
import { Syllabus } from "./store"
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { franc } from "franc";
|
|
3
|
+
import { BREATHECODE_HOST, DEV_MODE, RIGOBOT_HOST } from "./constants";
|
|
4
|
+
import { Lesson } from "../components/LessonItem";
|
|
5
|
+
import { randomUUID } from "./creatorUtils";
|
|
6
|
+
import { Syllabus } from "./store";
|
|
7
7
|
|
|
8
8
|
export function parseLesson(input: string, previous: Lesson[]): Lesson | null {
|
|
9
|
-
const pattern = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(.+)\]
|
|
10
|
-
const match = input.match(pattern)
|
|
9
|
+
const pattern = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(.+)\]$/;
|
|
10
|
+
const match = input.match(pattern);
|
|
11
11
|
|
|
12
|
-
if (!match) return null
|
|
12
|
+
if (!match) return null;
|
|
13
13
|
|
|
14
|
-
const [, index, title, type, description] = match
|
|
14
|
+
const [, index, title, type, description] = match;
|
|
15
15
|
|
|
16
16
|
const alreadyExistsIndex = previous.findIndex(
|
|
17
17
|
(lesson) => lesson.id === index && lesson.title === title
|
|
18
|
-
)
|
|
18
|
+
);
|
|
19
19
|
|
|
20
20
|
if (alreadyExistsIndex !== -1) {
|
|
21
21
|
return {
|
|
@@ -26,7 +26,7 @@ export function parseLesson(input: string, previous: Lesson[]): Lesson | null {
|
|
|
26
26
|
description: description.trim(),
|
|
27
27
|
duration: previous[alreadyExistsIndex].duration,
|
|
28
28
|
locked: previous[alreadyExistsIndex].locked || false,
|
|
29
|
-
}
|
|
29
|
+
};
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
return {
|
|
@@ -37,51 +37,51 @@ export function parseLesson(input: string, previous: Lesson[]): Lesson | null {
|
|
|
37
37
|
duration: 2,
|
|
38
38
|
uid: randomUUID(),
|
|
39
39
|
locked: false,
|
|
40
|
-
}
|
|
40
|
+
};
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export const uploadFileToBucket = async (content: string, path: string) => {
|
|
44
44
|
const response = await axios.post(`/upload`, {
|
|
45
45
|
content,
|
|
46
46
|
destination: path,
|
|
47
|
-
})
|
|
48
|
-
return response.data
|
|
49
|
-
}
|
|
47
|
+
});
|
|
48
|
+
return response.data;
|
|
49
|
+
};
|
|
50
50
|
export const uploadImageToBucket = async (imageUrl: string, path: string) => {
|
|
51
51
|
const response = await axios.post(`/upload-image`, {
|
|
52
52
|
image_url: imageUrl,
|
|
53
53
|
destination: path,
|
|
54
|
-
})
|
|
55
|
-
return response.data
|
|
56
|
-
}
|
|
54
|
+
});
|
|
55
|
+
return response.data;
|
|
56
|
+
};
|
|
57
57
|
|
|
58
58
|
export const checkParams = (paramsToCheck: string[]) => {
|
|
59
|
-
const urlParams = new URLSearchParams(window.location.search)
|
|
60
|
-
const result: Record<string, string> = {}
|
|
59
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
60
|
+
const result: Record<string, string> = {};
|
|
61
61
|
|
|
62
62
|
paramsToCheck.forEach((param) => {
|
|
63
|
-
const value = urlParams.get(param)
|
|
63
|
+
const value = urlParams.get(param);
|
|
64
64
|
if (value !== null) {
|
|
65
|
-
result[param] = value
|
|
65
|
+
result[param] = value;
|
|
66
66
|
}
|
|
67
|
-
})
|
|
67
|
+
});
|
|
68
68
|
|
|
69
|
-
return result
|
|
70
|
-
}
|
|
69
|
+
return result;
|
|
70
|
+
};
|
|
71
71
|
|
|
72
72
|
export async function getConsumables(token: string): Promise<any> {
|
|
73
|
-
const url = `${BREATHECODE_HOST}/v1/payments/me/service/consumable?virtual=true
|
|
73
|
+
const url = `${BREATHECODE_HOST}/v1/payments/me/service/consumable?virtual=true`;
|
|
74
74
|
|
|
75
75
|
const headers = {
|
|
76
76
|
Authorization: `Token ${token}`,
|
|
77
|
-
}
|
|
77
|
+
};
|
|
78
78
|
|
|
79
79
|
try {
|
|
80
|
-
const response = await axios.get(url, { headers })
|
|
81
|
-
return response.data
|
|
80
|
+
const response = await axios.get(url, { headers });
|
|
81
|
+
return response.data;
|
|
82
82
|
} catch (error) {
|
|
83
|
-
console.error("Error fetching consumables:", error)
|
|
84
|
-
throw error
|
|
83
|
+
console.error("Error fetching consumables:", error);
|
|
84
|
+
throw error;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -89,78 +89,78 @@ type ConsumableSlug =
|
|
|
89
89
|
| "ai-conversation-message"
|
|
90
90
|
| "ai-compilation"
|
|
91
91
|
| "ai-generation"
|
|
92
|
-
| "ai-course-generation"
|
|
92
|
+
| "ai-course-generation";
|
|
93
93
|
|
|
94
94
|
export async function useConsumableCall(
|
|
95
95
|
breathecodeToken: string,
|
|
96
96
|
consumableSlug: ConsumableSlug = "ai-conversation-message"
|
|
97
97
|
): Promise<boolean> {
|
|
98
|
-
const url = `${BREATHECODE_HOST}/v1/payments/me/service/${consumableSlug}/consumptionsession
|
|
98
|
+
const url = `${BREATHECODE_HOST}/v1/payments/me/service/${consumableSlug}/consumptionsession`;
|
|
99
99
|
|
|
100
100
|
const headers = {
|
|
101
101
|
Authorization: `Token ${breathecodeToken}`,
|
|
102
|
-
}
|
|
102
|
+
};
|
|
103
103
|
|
|
104
104
|
try {
|
|
105
|
-
const response = await axios.put(url, {}, { headers })
|
|
105
|
+
const response = await axios.put(url, {}, { headers });
|
|
106
106
|
|
|
107
107
|
if (response.status >= 200 && response.status < 300) {
|
|
108
|
-
console.log(`Successfully consumed ${consumableSlug}`)
|
|
109
|
-
return true
|
|
108
|
+
console.log(`Successfully consumed ${consumableSlug}`);
|
|
109
|
+
return true;
|
|
110
110
|
} else {
|
|
111
|
-
console.error(`Request failed with status code: ${response.status}`)
|
|
112
|
-
console.error(`Response: ${response.data}`)
|
|
113
|
-
return false
|
|
111
|
+
console.error(`Request failed with status code: ${response.status}`);
|
|
112
|
+
console.error(`Response: ${response.data}`);
|
|
113
|
+
return false;
|
|
114
114
|
}
|
|
115
115
|
} catch (error) {
|
|
116
|
-
console.error(`Error consuming ${consumableSlug}:`, error)
|
|
117
|
-
return false
|
|
116
|
+
console.error(`Error consuming ${consumableSlug}:`, error);
|
|
117
|
+
return false;
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
type ConsumableItem = {
|
|
122
|
-
id: number
|
|
123
|
-
how_many: number
|
|
124
|
-
unit_type: string
|
|
125
|
-
valid_until: string | null
|
|
126
|
-
}
|
|
122
|
+
id: number;
|
|
123
|
+
how_many: number;
|
|
124
|
+
unit_type: string;
|
|
125
|
+
valid_until: string | null;
|
|
126
|
+
};
|
|
127
127
|
|
|
128
128
|
type VoidEntry = {
|
|
129
|
-
id: number
|
|
130
|
-
slug: string
|
|
131
|
-
balance: { unit: number }
|
|
132
|
-
items: ConsumableItem[]
|
|
133
|
-
}
|
|
129
|
+
id: number;
|
|
130
|
+
slug: string;
|
|
131
|
+
balance: { unit: number };
|
|
132
|
+
items: ConsumableItem[];
|
|
133
|
+
};
|
|
134
134
|
|
|
135
135
|
export const parseConsumables = (
|
|
136
136
|
voids: VoidEntry[]
|
|
137
137
|
): Record<string, number> => {
|
|
138
|
-
const result: Record<string, number> = {}
|
|
138
|
+
const result: Record<string, number> = {};
|
|
139
139
|
|
|
140
140
|
voids.forEach((entry) => {
|
|
141
141
|
const maxHowMany = entry.items.length
|
|
142
142
|
? Math.max(...entry.items.map((item) => item.how_many))
|
|
143
|
-
: 0
|
|
144
|
-
result[entry.slug] = maxHowMany
|
|
145
|
-
})
|
|
143
|
+
: 0;
|
|
144
|
+
result[entry.slug] = maxHowMany;
|
|
145
|
+
});
|
|
146
146
|
|
|
147
|
-
return result
|
|
148
|
-
}
|
|
147
|
+
return result;
|
|
148
|
+
};
|
|
149
149
|
|
|
150
150
|
type LoginInfo = {
|
|
151
|
-
email: string
|
|
152
|
-
password: string
|
|
153
|
-
}
|
|
151
|
+
email: string;
|
|
152
|
+
password: string;
|
|
153
|
+
};
|
|
154
154
|
|
|
155
155
|
export const getRigobotJSON = async (breathecodeToken: string) => {
|
|
156
|
-
const rigoUrl = `${RIGOBOT_HOST}/v1/auth/me/token?breathecode_token=${breathecodeToken}
|
|
157
|
-
const rigoResp = await fetch(rigoUrl)
|
|
156
|
+
const rigoUrl = `${RIGOBOT_HOST}/v1/auth/me/token?breathecode_token=${breathecodeToken}`;
|
|
157
|
+
const rigoResp = await fetch(rigoUrl);
|
|
158
158
|
if (!rigoResp.ok) {
|
|
159
|
-
throw new Error("Unable to obtain Rigobot token")
|
|
159
|
+
throw new Error("Unable to obtain Rigobot token");
|
|
160
160
|
}
|
|
161
|
-
const rigobotJson = await rigoResp.json()
|
|
162
|
-
return rigobotJson
|
|
163
|
-
}
|
|
161
|
+
const rigobotJson = await rigoResp.json();
|
|
162
|
+
return rigobotJson;
|
|
163
|
+
};
|
|
164
164
|
export const validateUser = async (breathecodeToken: string) => {
|
|
165
165
|
const config = {
|
|
166
166
|
method: "GET",
|
|
@@ -168,30 +168,30 @@ export const validateUser = async (breathecodeToken: string) => {
|
|
|
168
168
|
"Content-Type": "application/json",
|
|
169
169
|
Authorization: `Token ${breathecodeToken}`,
|
|
170
170
|
},
|
|
171
|
-
}
|
|
171
|
+
};
|
|
172
172
|
|
|
173
|
-
const res = await fetch(`${BREATHECODE_HOST}/v1/auth/user/me`, config)
|
|
173
|
+
const res = await fetch(`${BREATHECODE_HOST}/v1/auth/user/me`, config);
|
|
174
174
|
if (!res.ok) {
|
|
175
|
-
console.log("ERROR", res)
|
|
176
|
-
return null
|
|
175
|
+
console.log("ERROR", res);
|
|
176
|
+
return null;
|
|
177
177
|
}
|
|
178
|
-
const json = await res.json()
|
|
178
|
+
const json = await res.json();
|
|
179
179
|
|
|
180
180
|
if ("roles" in json) {
|
|
181
|
-
delete json.roles
|
|
181
|
+
delete json.roles;
|
|
182
182
|
}
|
|
183
183
|
if ("permissions" in json) {
|
|
184
|
-
delete json.permissions
|
|
184
|
+
delete json.permissions;
|
|
185
185
|
}
|
|
186
186
|
if ("settings" in json) {
|
|
187
|
-
delete json.settings
|
|
187
|
+
delete json.settings;
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
return json
|
|
191
|
-
}
|
|
190
|
+
return json;
|
|
191
|
+
};
|
|
192
192
|
|
|
193
193
|
export const login4Geeks = async (loginInfo: LoginInfo) => {
|
|
194
|
-
const url = `${BREATHECODE_HOST}/v1/auth/login
|
|
194
|
+
const url = `${BREATHECODE_HOST}/v1/auth/login/`;
|
|
195
195
|
|
|
196
196
|
const res = await fetch(url, {
|
|
197
197
|
body: JSON.stringify(loginInfo),
|
|
@@ -199,87 +199,87 @@ export const login4Geeks = async (loginInfo: LoginInfo) => {
|
|
|
199
199
|
headers: {
|
|
200
200
|
"Content-Type": "application/json",
|
|
201
201
|
},
|
|
202
|
-
})
|
|
202
|
+
});
|
|
203
203
|
|
|
204
204
|
if (!res.ok) {
|
|
205
|
-
throw Error("Unable to login with provided credentials")
|
|
205
|
+
throw Error("Unable to login with provided credentials");
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
const json = await res.json()
|
|
208
|
+
const json = await res.json();
|
|
209
209
|
|
|
210
|
-
const rigoJson = await getRigobotJSON(json.token)
|
|
210
|
+
const rigoJson = await getRigobotJSON(json.token);
|
|
211
211
|
|
|
212
|
-
const user = await validateUser(json.token)
|
|
213
|
-
const returns = { ...json, rigobot: { ...rigoJson }, user }
|
|
212
|
+
const user = await validateUser(json.token);
|
|
213
|
+
const returns = { ...json, rigobot: { ...rigoJson }, user };
|
|
214
214
|
|
|
215
|
-
return returns
|
|
216
|
-
}
|
|
215
|
+
return returns;
|
|
216
|
+
};
|
|
217
217
|
|
|
218
218
|
export const loginWithToken = async (token: string) => {
|
|
219
|
-
const rigoJson = await getRigobotJSON(token)
|
|
219
|
+
const rigoJson = await getRigobotJSON(token);
|
|
220
220
|
|
|
221
|
-
const user = await validateUser(token)
|
|
221
|
+
const user = await validateUser(token);
|
|
222
222
|
|
|
223
|
-
const returns = { rigobot: { ...rigoJson }, ...user }
|
|
223
|
+
const returns = { rigobot: { ...rigoJson }, ...user };
|
|
224
224
|
|
|
225
|
-
return returns
|
|
226
|
-
}
|
|
225
|
+
return returns;
|
|
226
|
+
};
|
|
227
227
|
|
|
228
228
|
export const validateTokens = async (
|
|
229
229
|
breathecodeToken: string,
|
|
230
230
|
onValidRigoToken: (token: string) => void
|
|
231
231
|
) => {
|
|
232
|
-
const user = await validateUser(breathecodeToken)
|
|
233
|
-
console.log("USER", user)
|
|
232
|
+
const user = await validateUser(breathecodeToken);
|
|
233
|
+
console.log("USER", user);
|
|
234
234
|
if (!user) {
|
|
235
|
-
return false
|
|
235
|
+
return false;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
const rigobotJson = await getRigobotJSON(breathecodeToken)
|
|
238
|
+
const rigobotJson = await getRigobotJSON(breathecodeToken);
|
|
239
239
|
if (!rigobotJson) {
|
|
240
|
-
return false
|
|
240
|
+
return false;
|
|
241
241
|
}
|
|
242
|
-
onValidRigoToken(rigobotJson.key)
|
|
243
|
-
return true
|
|
244
|
-
}
|
|
242
|
+
onValidRigoToken(rigobotJson.key);
|
|
243
|
+
return true;
|
|
244
|
+
};
|
|
245
245
|
|
|
246
246
|
export function extractImagesFromMarkdown(markdown: string) {
|
|
247
|
-
const imageRegex = /!\[([^\]]*)]\(([^)]+)\)/g
|
|
248
|
-
const images = []
|
|
249
|
-
let match
|
|
247
|
+
const imageRegex = /!\[([^\]]*)]\(([^)]+)\)/g;
|
|
248
|
+
const images = [];
|
|
249
|
+
let match;
|
|
250
250
|
|
|
251
251
|
while ((match = imageRegex.exec(markdown)) !== null) {
|
|
252
|
-
const altText = match[1]
|
|
253
|
-
const url = match[2]
|
|
254
|
-
images.push({ alt: altText, url: url })
|
|
252
|
+
const altText = match[1];
|
|
253
|
+
const url = match[2];
|
|
254
|
+
images.push({ alt: altText, url: url });
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
return images
|
|
257
|
+
return images;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
export function getFilenameFromUrl(url: string): string {
|
|
261
261
|
try {
|
|
262
262
|
// 1) Use the URL constructor to strip off protocol/host/search/hash
|
|
263
|
-
const pathname = new URL(url, location.href).pathname
|
|
263
|
+
const pathname = new URL(url, location.href).pathname;
|
|
264
264
|
// 2) Grab everything after the last “/”
|
|
265
|
-
return pathname.substring(pathname.lastIndexOf("/") + 1)
|
|
265
|
+
return pathname.substring(pathname.lastIndexOf("/") + 1);
|
|
266
266
|
} catch {
|
|
267
267
|
// Fallback for non-absolute URLs or invalid inputs
|
|
268
|
-
const clean = url.split("?")[0].split("#")[0]
|
|
269
|
-
return clean.substring(clean.lastIndexOf("/") + 1)
|
|
268
|
+
const clean = url.split("?")[0].split("#")[0];
|
|
269
|
+
return clean.substring(clean.lastIndexOf("/") + 1);
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
export const makeCallbackUrl = (slug: string) => {
|
|
274
274
|
if (DEV_MODE) {
|
|
275
|
-
return `https://8000-charlytoc-rigobot-bmwdeam7cev.ws-us120.gitpod.io/v1/learnpack/tools/images/callback?slug=${slug}
|
|
275
|
+
return `https://8000-charlytoc-rigobot-bmwdeam7cev.ws-us120.gitpod.io/v1/learnpack/tools/images/callback?slug=${slug}`;
|
|
276
276
|
}
|
|
277
|
-
return `${window.location.origin}/api/v1/webhooks/images
|
|
278
|
-
}
|
|
277
|
+
return `${window.location.origin}/api/v1/webhooks/images`;
|
|
278
|
+
};
|
|
279
279
|
|
|
280
280
|
type TGenerateImageParams = {
|
|
281
|
-
prompt: string
|
|
282
|
-
}
|
|
281
|
+
prompt: string;
|
|
282
|
+
};
|
|
283
283
|
|
|
284
284
|
export const generateImage = async (
|
|
285
285
|
token: string,
|
|
@@ -298,14 +298,14 @@ export const generateImage = async (
|
|
|
298
298
|
Authorization: "Token " + token,
|
|
299
299
|
},
|
|
300
300
|
}
|
|
301
|
-
)
|
|
301
|
+
);
|
|
302
302
|
|
|
303
|
-
return response.data
|
|
303
|
+
return response.data;
|
|
304
304
|
} catch (error) {
|
|
305
|
-
console.error("Error generating image:", error)
|
|
306
|
-
return null
|
|
305
|
+
console.error("Error generating image:", error);
|
|
306
|
+
return null;
|
|
307
307
|
}
|
|
308
|
-
}
|
|
308
|
+
};
|
|
309
309
|
|
|
310
310
|
export const createCourse = async (
|
|
311
311
|
syllabus: Syllabus,
|
|
@@ -323,27 +323,27 @@ export const createCourse = async (
|
|
|
323
323
|
"x-rigo-token": token,
|
|
324
324
|
},
|
|
325
325
|
}
|
|
326
|
-
)
|
|
327
|
-
return response.data
|
|
328
|
-
}
|
|
326
|
+
);
|
|
327
|
+
return response.data;
|
|
328
|
+
};
|
|
329
329
|
|
|
330
330
|
interface SlugAvailabilityResponse {
|
|
331
|
-
slug: string
|
|
332
|
-
available: boolean
|
|
331
|
+
slug: string;
|
|
332
|
+
available: boolean;
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
export const isSlugAvailable = async (slug: string): Promise<boolean> => {
|
|
336
336
|
try {
|
|
337
337
|
const url = `${RIGOBOT_HOST}/v1/learnpack/check-slug-availability?slug=${encodeURIComponent(
|
|
338
338
|
slug
|
|
339
|
-
)}
|
|
340
|
-
const response = await axios.get<SlugAvailabilityResponse>(url)
|
|
341
|
-
return response.data.available
|
|
339
|
+
)}`;
|
|
340
|
+
const response = await axios.get<SlugAvailabilityResponse>(url);
|
|
341
|
+
return response.data.available;
|
|
342
342
|
} catch (error) {
|
|
343
|
-
console.error("Error checking slug availability:", error)
|
|
344
|
-
throw error
|
|
343
|
+
console.error("Error checking slug availability:", error);
|
|
344
|
+
throw error;
|
|
345
345
|
}
|
|
346
|
-
}
|
|
346
|
+
};
|
|
347
347
|
|
|
348
348
|
export const reWriteTitle = async (title: string, token: string) => {
|
|
349
349
|
// We hav in the parsed the newTitle
|
|
@@ -363,25 +363,25 @@ export const reWriteTitle = async (title: string, token: string) => {
|
|
|
363
363
|
Authorization: "Token " + token,
|
|
364
364
|
},
|
|
365
365
|
}
|
|
366
|
-
)
|
|
367
|
-
console.log("RESPONSE", response.data)
|
|
368
|
-
return response.data.parsed.newTitle
|
|
366
|
+
);
|
|
367
|
+
console.log("RESPONSE", response.data);
|
|
368
|
+
return response.data.parsed.newTitle;
|
|
369
369
|
} catch (error) {
|
|
370
|
-
console.error("Error rewriting title:", error)
|
|
370
|
+
console.error("Error rewriting title:", error);
|
|
371
371
|
// Return the title as it is with a random number of 4 characters
|
|
372
|
-
return `${title} ${Math.random().toString(36).substring(2, 6)}
|
|
372
|
+
return `${title} ${Math.random().toString(36).substring(2, 6)}`;
|
|
373
373
|
}
|
|
374
|
-
}
|
|
374
|
+
};
|
|
375
375
|
|
|
376
376
|
export async function registerUserWithFormData(
|
|
377
377
|
firstName: string,
|
|
378
378
|
lastName: string,
|
|
379
379
|
email: string
|
|
380
380
|
): Promise<any> {
|
|
381
|
-
const formData = new FormData()
|
|
382
|
-
formData.append("1_first_name", firstName)
|
|
383
|
-
formData.append("1_last_name", lastName)
|
|
384
|
-
formData.append("1_email", email)
|
|
381
|
+
const formData = new FormData();
|
|
382
|
+
formData.append("1_first_name", firstName);
|
|
383
|
+
formData.append("1_last_name", lastName);
|
|
384
|
+
formData.append("1_email", email);
|
|
385
385
|
|
|
386
386
|
// Puedes modificar este objeto para agregar info real de tracking si la tienes.
|
|
387
387
|
const conversionArray = [
|
|
@@ -402,9 +402,9 @@ export async function registerUserWithFormData(
|
|
|
402
402
|
internal_cta_content: "$undefined",
|
|
403
403
|
internal_cta_campaign: "$undefined",
|
|
404
404
|
},
|
|
405
|
-
]
|
|
405
|
+
];
|
|
406
406
|
|
|
407
|
-
formData.append("0", JSON.stringify(conversionArray))
|
|
407
|
+
formData.append("0", JSON.stringify(conversionArray));
|
|
408
408
|
|
|
409
409
|
try {
|
|
410
410
|
const response = await axios.post(
|
|
@@ -415,57 +415,57 @@ export async function registerUserWithFormData(
|
|
|
415
415
|
"Content-Type": "multipart/form-data",
|
|
416
416
|
},
|
|
417
417
|
}
|
|
418
|
-
)
|
|
419
|
-
return response.data
|
|
418
|
+
);
|
|
419
|
+
return response.data;
|
|
420
420
|
} catch (error: any) {
|
|
421
421
|
// Manejo de errores básico
|
|
422
|
-
console.error(error, "ERROR REGISTERING IN LEARNPACK")
|
|
422
|
+
console.error(error, "ERROR REGISTERING IN LEARNPACK");
|
|
423
423
|
return {
|
|
424
424
|
success: false,
|
|
425
425
|
message: error?.response?.data?.detail || "Registration error",
|
|
426
426
|
data: error?.response?.data || null,
|
|
427
|
-
}
|
|
427
|
+
};
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
|
|
431
431
|
export const isValidRigoToken = async (rigobotToken: string) => {
|
|
432
|
-
const rigoUrl = `${RIGOBOT_HOST}/v1/auth/token/${rigobotToken}
|
|
433
|
-
const rigoResp = await fetch(rigoUrl)
|
|
432
|
+
const rigoUrl = `${RIGOBOT_HOST}/v1/auth/token/${rigobotToken}`;
|
|
433
|
+
const rigoResp = await fetch(rigoUrl);
|
|
434
434
|
if (!rigoResp.ok) {
|
|
435
|
-
return false
|
|
435
|
+
return false;
|
|
436
436
|
}
|
|
437
437
|
|
|
438
|
-
return true
|
|
439
|
-
}
|
|
438
|
+
return true;
|
|
439
|
+
};
|
|
440
440
|
export const isValidPublicToken = async (publicToken: string) => {
|
|
441
441
|
const headers = {
|
|
442
442
|
"Content-Type": "application/json",
|
|
443
443
|
Authorization: "Token " + publicToken,
|
|
444
|
-
}
|
|
445
|
-
const rigoUrl = `${RIGOBOT_HOST}/v1/auth/public/token/validate
|
|
446
|
-
const rigoResp = await fetch(rigoUrl, { headers })
|
|
444
|
+
};
|
|
445
|
+
const rigoUrl = `${RIGOBOT_HOST}/v1/auth/public/token/validate`;
|
|
446
|
+
const rigoResp = await fetch(rigoUrl, { headers });
|
|
447
447
|
if (!rigoResp.ok) {
|
|
448
|
-
return false
|
|
448
|
+
return false;
|
|
449
449
|
}
|
|
450
450
|
|
|
451
|
-
return true
|
|
452
|
-
}
|
|
451
|
+
return true;
|
|
452
|
+
};
|
|
453
453
|
|
|
454
454
|
export const fixTitleLength = (title: string) => {
|
|
455
|
-
const MAX_LENGTH = 49
|
|
456
|
-
let fixed = title.slice(0, MAX_LENGTH)
|
|
457
|
-
fixed = fixed.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "")
|
|
458
|
-
return fixed
|
|
459
|
-
}
|
|
455
|
+
const MAX_LENGTH = 49;
|
|
456
|
+
let fixed = title.slice(0, MAX_LENGTH);
|
|
457
|
+
fixed = fixed.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "");
|
|
458
|
+
return fixed;
|
|
459
|
+
};
|
|
460
460
|
|
|
461
461
|
export const getTechnologies = async () => {
|
|
462
|
-
const response = await axios.get(`/technologies`)
|
|
463
|
-
return response.data
|
|
464
|
-
}
|
|
462
|
+
const response = await axios.get(`/technologies`);
|
|
463
|
+
return response.data;
|
|
464
|
+
};
|
|
465
465
|
|
|
466
466
|
export const detectLanguage = (text: string) => {
|
|
467
|
-
const lang = franc(text)
|
|
468
|
-
if (lang === "spa") return "es"
|
|
469
|
-
if (lang === "eng") return "en"
|
|
470
|
-
return "en" // fallback to English
|
|
471
|
-
}
|
|
467
|
+
const lang = franc(text);
|
|
468
|
+
if (lang === "spa") return "es";
|
|
469
|
+
if (lang === "eng") return "en";
|
|
470
|
+
return "en"; // fallback to English
|
|
471
|
+
};
|