@learnpack/learnpack 5.0.65 → 5.0.67
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/README.md +13 -13
- package/lib/commands/serve.js +15 -15
- package/{src/creatorDist/assets/index-tt9JBVY0.css → lib/creatorDist/assets/index-t6ma_gVm.css} +118 -20
- package/lib/creatorDist/assets/index-tZYXMzIW.js +75067 -0
- package/lib/creatorDist/assets/pdf.worker-DSVOJ9H9.js +56037 -0
- package/lib/creatorDist/index.html +10 -5
- package/lib/creatorDist/logo-192 copy.png +0 -0
- package/lib/creatorDist/logo.png +0 -0
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/src/commands/serve.ts +24 -20
- package/src/creator/index.html +8 -3
- package/src/creator/package-lock.json +394 -0
- package/src/creator/package.json +3 -0
- package/src/creator/public/logo-192 copy.png +0 -0
- package/src/creator/public/logo.png +0 -0
- package/src/creator/src/App.tsx +30 -4
- package/src/creator/src/assets/svgs.tsx +138 -0
- package/src/creator/src/components/FileUploader.tsx +91 -0
- package/src/creator/src/components/LessonItem.tsx +70 -0
- package/src/creator/src/components/Loader.tsx +64 -19
- package/src/creator/src/components/Login.tsx +6 -12
- package/src/creator/src/components/Message.tsx +28 -0
- package/src/creator/src/components/RigoLoader.tsx +14 -0
- package/src/creator/src/components/StepWizard.tsx +1 -0
- package/src/creator/src/components/SyllabusEditor.tsx +111 -261
- package/src/creator/src/index.css +64 -0
- package/src/creator/src/utils/creatorUtils.ts +136 -0
- package/src/creator/src/utils/eventBus.ts +2 -0
- package/src/creator/src/utils/lib.ts +6 -0
- package/src/creator/src/utils/store.ts +6 -1
- package/{lib/creatorDist/assets/index-tt9JBVY0.css → src/creatorDist/assets/index-t6ma_gVm.css} +118 -20
- package/src/creatorDist/assets/index-tZYXMzIW.js +75067 -0
- package/src/creatorDist/assets/pdf.worker-DSVOJ9H9.js +56037 -0
- package/src/creatorDist/index.html +10 -5
- package/src/creatorDist/logo-192 copy.png +0 -0
- package/src/creatorDist/logo.png +0 -0
- package/src/ui/_app/app.css +1 -1
- package/src/ui/_app/app.js +299 -299
- package/src/ui/app.tar.gz +0 -0
- package/lib/creatorDist/assets/index-CrrS9sA3.js +0 -23718
- package/src/creator/src/App.css +0 -42
- package/src/creatorDist/assets/index-CrrS9sA3.js +0 -23718
@@ -85,4 +85,142 @@ export const SVGS = {
|
|
85
85
|
</g>
|
86
86
|
</svg>
|
87
87
|
),
|
88
|
+
rigoSoftBlue: (
|
89
|
+
<svg
|
90
|
+
width="25"
|
91
|
+
height="15"
|
92
|
+
viewBox="0 0 18 11"
|
93
|
+
fill="none"
|
94
|
+
xmlns="http://www.w3.org/2000/svg"
|
95
|
+
>
|
96
|
+
<path
|
97
|
+
d="M17.1812 3.46636H16.7418V3.32743C16.7418 2.09446 15.7417 1.09375 14.51 1.09375H13.3627L13.7718 1.85133C14.2502 1.94685 14.642 2.28548 14.8195 2.73699H2.64959C2.86173 2.20299 3.37477 1.82529 3.97439 1.82529H11.54L11.934 1.09592H2.96131C1.72743 1.09375 0.727339 2.09228 0.727339 3.32743V3.46636H0.287905C0.127717 3.46636 0 3.59443 0 3.75289V7.56252C0 7.72098 0.129882 7.84905 0.287905 7.84905H1.82051V7.99015C1.82051 8.13125 1.8703 8.26366 1.95256 8.36569C1.96338 8.38088 1.97637 8.39391 1.98936 8.40693C2.01533 8.43298 2.04348 8.45686 2.07378 8.47857C2.11924 8.51113 2.17119 8.535 2.22531 8.55237C2.27943 8.56974 2.33787 8.57842 2.39632 8.57842H2.54785H7.58078L8.27997 6.38815L8.59386 5.40047C8.63931 5.25721 8.83197 5.25721 8.87743 5.40047L9.19131 6.38815L9.89051 8.57842H14.9234H15.075C15.1637 8.57842 15.2481 8.55671 15.3239 8.51981C15.365 8.4981 15.404 8.47422 15.4408 8.44383C15.4689 8.41996 15.4949 8.39391 15.5187 8.36352C15.536 8.34181 15.5534 8.31793 15.5664 8.29405C15.6183 8.20505 15.6508 8.10086 15.6508 7.98798V7.84688H17.1812C17.3414 7.84688 17.4691 7.71881 17.4691 7.56035V3.75072C17.4691 3.59226 17.3392 3.46418 17.1812 3.46418V3.46636ZM15.2958 7.82301C15.2958 8.04008 15.1204 8.21374 14.9061 8.21374H10.0723L9.61992 6.96991L8.85578 4.87082C8.81466 4.75577 8.6523 4.75577 8.60901 4.87082L7.84487 6.96991L7.39245 8.21374H2.563C2.34653 8.21374 2.17336 8.03791 2.17336 7.82301V3.46853C2.17336 3.25145 2.3487 3.07779 2.563 3.07779H14.9061C15.1226 3.07779 15.2958 3.25362 15.2958 3.46853V7.82084V7.82301Z"
|
98
|
+
fill="url(#paint0_linear_1485_1767)"
|
99
|
+
/>
|
100
|
+
<path
|
101
|
+
d="M2.6496 2.73592C2.86174 2.20193 3.37477 1.82422 3.97439 1.82422H11.54H3.97656C3.37694 1.82422 2.8639 2.20193 2.65176 2.73592H2.6496Z"
|
102
|
+
fill="#080B16"
|
103
|
+
/>
|
104
|
+
<path
|
105
|
+
d="M14.8196 2.73722C14.6421 2.28788 14.2502 1.94707 13.7719 1.85156C14.2502 1.94707 14.6421 2.28571 14.8196 2.73722Z"
|
106
|
+
fill="#080B16"
|
107
|
+
/>
|
108
|
+
<path
|
109
|
+
d="M13.0033 8.57837H9.89045L9.19125 6.3881L8.87737 5.40042C8.83191 5.25715 8.63925 5.25715 8.5938 5.40042L8.27991 6.3881L7.58072 8.57837H2.54779V9.49441C2.54779 10.2976 3.18638 10.951 3.97649 10.951H8.11973C13.7934 10.8403 13.0119 8.59573 13.0055 8.57837H13.0033Z"
|
110
|
+
fill="#B0EFFF"
|
111
|
+
/>
|
112
|
+
<path
|
113
|
+
d="M8.11768 10.9507H13.4948C14.2827 10.9507 14.9235 10.2995 14.9235 9.49417V8.57812H13.0034C13.0099 8.59549 13.7914 10.84 8.11768 10.9507Z"
|
114
|
+
fill="url(#paint1_linear_1485_1767)"
|
115
|
+
/>
|
116
|
+
<path
|
117
|
+
d="M13.0445 2.7362H14.8195C14.642 2.28469 14.2502 1.94606 13.7718 1.85055L13.3627 1.09296L12.8259 0.100939C12.7523 -0.0336463 12.5444 -0.0336463 12.473 0.100939L12.1028 0.784718L12.6224 1.8614C13.2718 2.26298 13.0488 2.72752 13.0445 2.7362Z"
|
118
|
+
fill="url(#paint2_linear_1485_1767)"
|
119
|
+
/>
|
120
|
+
<path
|
121
|
+
d="M2.65176 2.73664H13.0445C13.0445 2.73664 13.2696 2.26342 12.6224 1.86184C12.6029 1.84881 12.5812 1.83579 12.5596 1.82493L12.1028 0.785156L11.9362 1.09557L11.5422 1.82493H3.97439C3.37477 1.82493 2.86174 2.20264 2.6496 2.73664H2.65176Z"
|
122
|
+
fill="#B0EFFF"
|
123
|
+
/>
|
124
|
+
<path
|
125
|
+
d="M12.6202 1.86184L12.1007 0.785156L12.5575 1.82493C12.5791 1.83796 12.6008 1.84881 12.6202 1.86184Z"
|
126
|
+
fill="#C7F3FD"
|
127
|
+
/>
|
128
|
+
<path
|
129
|
+
d="M14.9062 3.07812H2.56305C2.34658 3.07812 2.1734 3.25395 2.1734 3.46886V7.82117C2.1734 8.03824 2.34874 8.2119 2.56305 8.2119H7.39465L7.84708 6.96807L8.61122 4.86898C8.65234 4.75393 8.8147 4.75393 8.85799 4.86898L9.62213 6.96807L10.0746 8.2119H14.9083C15.1248 8.2119 15.298 8.03607 15.298 7.82117V3.46886C15.298 3.25178 15.1226 3.07812 14.9083 3.07812H14.9062ZM5.27758 3.82268V6.38414V7.30453C5.27758 7.50207 5.11523 7.6627 4.91391 7.6627C4.71259 7.6627 4.55024 7.50207 4.55024 7.30453V3.82268C4.55024 3.62515 4.71259 3.46451 4.91391 3.46451C5.11523 3.46451 5.27758 3.62515 5.27758 3.82268ZM12.9233 3.82268V6.38414V7.30453C12.9233 7.50207 12.7609 7.6627 12.5596 7.6627C12.3583 7.6627 12.196 7.50207 12.196 7.30453V3.82268C12.196 3.62515 12.3583 3.46451 12.5596 3.46451C12.7609 3.46451 12.9233 3.62515 12.9233 3.82268Z"
|
130
|
+
fill="#080B16"
|
131
|
+
/>
|
132
|
+
<path
|
133
|
+
d="M4.91384 3.46484C4.71252 3.46484 4.55017 3.62548 4.55017 3.82301V7.30486C4.55017 7.5024 4.71252 7.66303 4.91384 7.66303C5.11516 7.66303 5.27751 7.5024 5.27751 7.30486V6.38664V3.82301C5.27751 3.62548 5.11516 3.46484 4.91384 3.46484Z"
|
134
|
+
fill="#E95B17"
|
135
|
+
/>
|
136
|
+
<path
|
137
|
+
d="M12.5574 3.46484C12.3561 3.46484 12.1937 3.62548 12.1937 3.82301V7.30486C12.1937 7.5024 12.3561 7.66303 12.5574 7.66303C12.7587 7.66303 12.9211 7.5024 12.9211 7.30486V6.38664V3.82301C12.9211 3.62548 12.7587 3.46484 12.5574 3.46484Z"
|
138
|
+
fill="#0084FF"
|
139
|
+
/>
|
140
|
+
<defs>
|
141
|
+
<linearGradient
|
142
|
+
id="paint0_linear_1485_1767"
|
143
|
+
x1="10.5789"
|
144
|
+
y1="0.294922"
|
145
|
+
x2="7.57889"
|
146
|
+
y2="8.97052"
|
147
|
+
gradientUnits="userSpaceOnUse"
|
148
|
+
>
|
149
|
+
<stop stopColor="#080B16" />
|
150
|
+
<stop offset="1" stopColor="#161F2C" />
|
151
|
+
</linearGradient>
|
152
|
+
<linearGradient
|
153
|
+
id="paint1_linear_1485_1767"
|
154
|
+
x1="8.11768"
|
155
|
+
y1="9.76334"
|
156
|
+
x2="14.9235"
|
157
|
+
y2="9.76334"
|
158
|
+
gradientUnits="userSpaceOnUse"
|
159
|
+
>
|
160
|
+
<stop stopColor="#B0EFFF" />
|
161
|
+
<stop offset="0.44" stopColor="#ADECFE" />
|
162
|
+
<stop offset="0.67" stopColor="#A5E4FE" />
|
163
|
+
<stop offset="0.85" stopColor="#98D7FD" />
|
164
|
+
<stop offset="1" stopColor="#86C5FD" />
|
165
|
+
</linearGradient>
|
166
|
+
<linearGradient
|
167
|
+
id="paint2_linear_1485_1767"
|
168
|
+
x1="11.2543"
|
169
|
+
y1="1.91784"
|
170
|
+
x2="13.5278"
|
171
|
+
y2="1.41473"
|
172
|
+
gradientUnits="userSpaceOnUse"
|
173
|
+
>
|
174
|
+
<stop stopColor="#B0EFFF" />
|
175
|
+
<stop offset="0.44" stopColor="#ADECFE" />
|
176
|
+
<stop offset="0.67" stopColor="#A5E4FE" />
|
177
|
+
<stop offset="0.85" stopColor="#98D7FD" />
|
178
|
+
<stop offset="1" stopColor="#86C5FD" />
|
179
|
+
</linearGradient>
|
180
|
+
</defs>
|
181
|
+
</svg>
|
182
|
+
),
|
183
|
+
send: (
|
184
|
+
<svg
|
185
|
+
width="12"
|
186
|
+
height="15"
|
187
|
+
viewBox="0 0 12 15"
|
188
|
+
fill="none"
|
189
|
+
xmlns="http://www.w3.org/2000/svg"
|
190
|
+
>
|
191
|
+
<path
|
192
|
+
d="M6.12812 3.64814L0.384343 0.0378137C0.213539 -0.0696296 0 0.0647108 0 0.279307V5.34833C0 5.47075 0.0733163 5.57892 0.18082 5.61498L2.90314 6.52715L5.01075 7.23331C5.25193 7.31415 5.25193 7.68577 5.01075 7.76646L2.90314 8.47262L0.18082 9.38509C0.0733163 9.42114 0 9.52931 0 9.65173V14.7206C0 14.9354 0.213539 15.0695 0.384343 14.9622L6.12812 11.3519L11.8719 7.7416C12.0427 7.6343 12.0427 7.36576 11.8719 7.25847L6.12812 3.64814Z"
|
193
|
+
fill="#C7F3FD"
|
194
|
+
/>
|
195
|
+
</svg>
|
196
|
+
),
|
197
|
+
clip: (
|
198
|
+
<svg
|
199
|
+
fill="#C7F3FD"
|
200
|
+
width="20"
|
201
|
+
height="20"
|
202
|
+
viewBox="0 0 32 32"
|
203
|
+
version="1.1"
|
204
|
+
xmlns="http://www.w3.org/2000/svg"
|
205
|
+
>
|
206
|
+
<title>clip</title>
|
207
|
+
<path d="M5.469 16.688l8.75-8.75c0.094-0.094 0.844-0.844 2.031-1.25 1.656-0.531 3.344-0.094 4.688 1.25 1.375 1.344 1.781 3 1.25 4.656-0.375 1.188-1.156 2-1.25 2.094l-9.406 9.406c-1.625 1.625-5.688 3.719-9.438 0-3.719-3.719-1.594-7.813 0-9.406l10.094-10.125c0.375-0.375 0.969-0.375 1.344 0s0.375 0.969 0 1.344l-10.063 10.125c-0.156 0.125-3.313 3.406 0 6.719 3.219 3.219 6.375 0.344 6.719 0l9.406-9.438s0.531-0.531 0.781-1.281c0.313-1 0.094-1.875-0.781-2.75-1.875-1.875-3.688-0.313-4.031 0l-8.75 8.719c-0.313 0.313-0.531 0.844 0 1.375s1.031 0.281 1.344 0l6.063-6.063c0.375-0.344 1-0.344 1.344 0 0.375 0.375 0.375 1 0 1.375l-6.063 6.031c-0.844 0.813-2.563 1.469-4.031 0-1.5-1.469-0.844-3.219 0-4.031z"></path>
|
208
|
+
</svg>
|
209
|
+
),
|
210
|
+
user: (
|
211
|
+
<svg
|
212
|
+
width="20"
|
213
|
+
height="20"
|
214
|
+
viewBox="0 0 24 24"
|
215
|
+
fill="none"
|
216
|
+
xmlns="http://www.w3.org/2000/svg"
|
217
|
+
>
|
218
|
+
<circle cx="12" cy="6" r="4" stroke="#1C398E" strokeWidth="1.5" />
|
219
|
+
<path
|
220
|
+
d="M20 17.5C20 19.9853 20 22 12 22C4 22 4 19.9853 4 17.5C4 15.0147 7.58172 13 12 13C16.4183 13 20 15.0147 20 17.5Z"
|
221
|
+
stroke="#1C398E"
|
222
|
+
strokeWidth="1.5"
|
223
|
+
/>
|
224
|
+
</svg>
|
225
|
+
),
|
88
226
|
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import React, { useRef } from "react"
|
2
|
+
import * as pdfjsLib from "pdfjs-dist"
|
3
|
+
import mammoth from "mammoth"
|
4
|
+
import { SVGS } from "../assets/svgs"
|
5
|
+
import pdfWorker from "pdfjs-dist/build/pdf.worker?worker"
|
6
|
+
|
7
|
+
pdfjsLib.GlobalWorkerOptions.workerPort = new pdfWorker()
|
8
|
+
|
9
|
+
const allowedTypes = [
|
10
|
+
"application/pdf",
|
11
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
12
|
+
"text/plain",
|
13
|
+
"text/markdown",
|
14
|
+
]
|
15
|
+
|
16
|
+
export interface ParsedFile {
|
17
|
+
name: string
|
18
|
+
text: string
|
19
|
+
}
|
20
|
+
|
21
|
+
interface FileUploaderProps {
|
22
|
+
onResult: (files: ParsedFile[]) => void
|
23
|
+
}
|
24
|
+
|
25
|
+
const FileUploader: React.FC<FileUploaderProps> = ({ onResult }) => {
|
26
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
27
|
+
|
28
|
+
const extractText = async (file: File): Promise<ParsedFile> => {
|
29
|
+
const { type, name } = file
|
30
|
+
|
31
|
+
if (type === "application/pdf") {
|
32
|
+
const arrayBuffer = await file.arrayBuffer()
|
33
|
+
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise
|
34
|
+
let text = ""
|
35
|
+
|
36
|
+
for (let i = 0; i < pdf.numPages; i++) {
|
37
|
+
const page = await pdf.getPage(i + 1)
|
38
|
+
const content = await page.getTextContent()
|
39
|
+
text += content.items.map((item: any) => item.str).join(" ") + "\n"
|
40
|
+
}
|
41
|
+
|
42
|
+
return { name, text }
|
43
|
+
}
|
44
|
+
|
45
|
+
if (
|
46
|
+
type ===
|
47
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
48
|
+
) {
|
49
|
+
const arrayBuffer = await file.arrayBuffer()
|
50
|
+
const { value } = await mammoth.extractRawText({ arrayBuffer })
|
51
|
+
return { name, text: value }
|
52
|
+
}
|
53
|
+
|
54
|
+
const text = await file.text()
|
55
|
+
return { name, text }
|
56
|
+
}
|
57
|
+
|
58
|
+
const handleFiles = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
59
|
+
const inputFiles = e.target.files
|
60
|
+
if (!inputFiles) return
|
61
|
+
|
62
|
+
const files = Array.from(inputFiles).filter((file) =>
|
63
|
+
allowedTypes.includes(file.type)
|
64
|
+
)
|
65
|
+
const parsed = await Promise.all(files.map(extractText))
|
66
|
+
onResult(parsed)
|
67
|
+
}
|
68
|
+
|
69
|
+
return (
|
70
|
+
<>
|
71
|
+
<button
|
72
|
+
type="button"
|
73
|
+
className="cursor-pointer blue-on-hover flex items-center justify-center w-6 h-6"
|
74
|
+
onClick={() => inputRef.current?.click()}
|
75
|
+
>
|
76
|
+
{SVGS.clip}
|
77
|
+
</button>
|
78
|
+
|
79
|
+
<input
|
80
|
+
ref={inputRef}
|
81
|
+
type="file"
|
82
|
+
multiple
|
83
|
+
accept=".pdf,.docx,.txt,.md"
|
84
|
+
onChange={handleFiles}
|
85
|
+
style={{ display: "none" }}
|
86
|
+
/>
|
87
|
+
</>
|
88
|
+
)
|
89
|
+
}
|
90
|
+
|
91
|
+
export default FileUploader
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import { useState } from "react"
|
2
|
+
import { SVGS } from "../assets/svgs"
|
3
|
+
|
4
|
+
export interface Lesson {
|
5
|
+
id: string
|
6
|
+
title: string
|
7
|
+
type: "READ" | "CODE" | "QUIZ"
|
8
|
+
description: string
|
9
|
+
duration?: number
|
10
|
+
}
|
11
|
+
|
12
|
+
interface LessonItemProps {
|
13
|
+
lesson: Lesson
|
14
|
+
index: string
|
15
|
+
isNew: boolean
|
16
|
+
onChange: (id: string, newTitle: string) => void
|
17
|
+
onRemove: (id: string) => void
|
18
|
+
}
|
19
|
+
|
20
|
+
export const LessonItem: React.FC<LessonItemProps> = ({
|
21
|
+
lesson,
|
22
|
+
index,
|
23
|
+
onChange,
|
24
|
+
onRemove,
|
25
|
+
isNew,
|
26
|
+
}) => {
|
27
|
+
const [isEditing, setIsEditing] = useState(false)
|
28
|
+
|
29
|
+
return (
|
30
|
+
<div
|
31
|
+
className={`flex items-center space-x-2 border border-gray-200 rounded-md p-3 ${
|
32
|
+
isNew ? "bg-yellow-50" : ""
|
33
|
+
}`}
|
34
|
+
>
|
35
|
+
<span className="index-circle">{index}</span>
|
36
|
+
<span className="text-gray-500 text-sm">
|
37
|
+
{lesson.type[0] + lesson.type.slice(1).toLowerCase()} ●
|
38
|
+
</span>
|
39
|
+
|
40
|
+
{isEditing ? (
|
41
|
+
<input
|
42
|
+
value={lesson.title}
|
43
|
+
onChange={(e) => onChange(lesson.id, e.target.value)}
|
44
|
+
onBlur={() => setIsEditing(false)}
|
45
|
+
autoFocus
|
46
|
+
className="flex-1 bg-white border border-gray-300 rounded-md px-2 py-1 text-sm"
|
47
|
+
/>
|
48
|
+
) : (
|
49
|
+
<span className="flex-1 text-sm text-gray-800">{lesson.title}</span>
|
50
|
+
)}
|
51
|
+
|
52
|
+
<span className="text-sm text-gray-600 bg-blue-100 px-2 py-1 rounded-full">
|
53
|
+
{lesson.duration} min
|
54
|
+
</span>
|
55
|
+
|
56
|
+
<button
|
57
|
+
onClick={() => setIsEditing(!isEditing)}
|
58
|
+
className="text-gray-500 hover:text-blue-500 cursor-pointer "
|
59
|
+
>
|
60
|
+
{SVGS.pen}
|
61
|
+
</button>
|
62
|
+
<button
|
63
|
+
onClick={() => onRemove(lesson.id)}
|
64
|
+
className="text-red-500 hover:text-red-700 cursor-pointer"
|
65
|
+
>
|
66
|
+
{SVGS.trash}
|
67
|
+
</button>
|
68
|
+
</div>
|
69
|
+
)
|
70
|
+
}
|
@@ -1,28 +1,73 @@
|
|
1
|
-
import React from
|
1
|
+
import React, { useEffect, useRef, useState } from "react"
|
2
|
+
import { eventBus } from "../utils/eventBus"
|
2
3
|
|
3
4
|
interface LoaderProps {
|
4
|
-
text: string
|
5
|
-
icon?: React.ReactNode
|
5
|
+
text: string
|
6
|
+
icon?: React.ReactNode
|
7
|
+
listeningTo?: string
|
8
|
+
initialBuffer?: string
|
6
9
|
}
|
7
10
|
|
8
|
-
const Loader: React.FC<LoaderProps> = ({
|
11
|
+
const Loader: React.FC<LoaderProps> = ({
|
12
|
+
text,
|
13
|
+
icon,
|
14
|
+
listeningTo,
|
15
|
+
initialBuffer,
|
16
|
+
}) => {
|
17
|
+
const [buffer, setBuffer] = useState(initialBuffer || "")
|
18
|
+
const preRef = useRef<HTMLPreElement>(null)
|
19
|
+
|
20
|
+
useEffect(() => {
|
21
|
+
if (listeningTo) {
|
22
|
+
eventBus.on(listeningTo, (e: any) => {
|
23
|
+
setBuffer((prev) => prev + "\n" + e.message)
|
24
|
+
})
|
25
|
+
}
|
26
|
+
return () => {
|
27
|
+
if (listeningTo) {
|
28
|
+
eventBus.off(listeningTo)
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}, [listeningTo])
|
32
|
+
|
33
|
+
useEffect(() => {
|
34
|
+
if (preRef.current) {
|
35
|
+
preRef.current.scrollTo({
|
36
|
+
top: preRef.current.scrollHeight,
|
37
|
+
behavior: "smooth",
|
38
|
+
})
|
39
|
+
}
|
40
|
+
}, [buffer])
|
41
|
+
|
9
42
|
return (
|
10
43
|
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-50 text-center space-y-6">
|
11
|
-
<div className="text-blue-500 text-4xl animate-pulse">
|
12
|
-
{icon}
|
13
|
-
</div>
|
44
|
+
<div className="text-blue-500 text-4xl animate-pulse">{icon}</div>
|
14
45
|
<p className="text-gray-800 text-lg whitespace-pre-line">{text}</p>
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
46
|
+
{!buffer && (
|
47
|
+
<div className="flex space-x-2 mt-2">
|
48
|
+
{[0, 1, 2, 3].map((i) => (
|
49
|
+
<span
|
50
|
+
key={i}
|
51
|
+
className="w-2 h-2 rounded-full bg-blue-400 opacity-30 animate-ping"
|
52
|
+
style={{
|
53
|
+
animationDelay: `${i * 0.2}s`,
|
54
|
+
animationDuration: "1.2s",
|
55
|
+
}}
|
56
|
+
/>
|
57
|
+
))}
|
58
|
+
</div>
|
59
|
+
)}
|
60
|
+
{buffer && (
|
61
|
+
<pre
|
62
|
+
ref={preRef}
|
63
|
+
className="text-gray-800 text-sm border border-blue-200 rounded-md p-3 font-sans max-h-[300px] overflow-y-auto w-full max-w-[700px] text-left"
|
64
|
+
style={{ scrollbarWidth: "none" }}
|
65
|
+
>
|
66
|
+
{buffer.trim()}
|
67
|
+
</pre>
|
68
|
+
)}
|
24
69
|
</div>
|
25
|
-
)
|
26
|
-
}
|
70
|
+
)
|
71
|
+
}
|
27
72
|
|
28
|
-
export default Loader
|
73
|
+
export default Loader
|
@@ -4,19 +4,13 @@ import { SVGS } from "../assets/svgs"
|
|
4
4
|
import toast from "react-hot-toast"
|
5
5
|
import useStore from "../utils/store"
|
6
6
|
import { useShallow } from "zustand/react/shallow"
|
7
|
+
import { checkParams } from "../utils/lib"
|
7
8
|
|
8
9
|
type LoginInfo = {
|
9
10
|
email: string
|
10
11
|
password: string
|
11
12
|
}
|
12
13
|
|
13
|
-
const checkParams = () => {
|
14
|
-
const urlParams = new URLSearchParams(window.location.search)
|
15
|
-
const token = urlParams.get("token")
|
16
|
-
|
17
|
-
return { token }
|
18
|
-
}
|
19
|
-
|
20
14
|
const getRigobotJSON = async (breathecodeToken: string) => {
|
21
15
|
const rigoUrl = `${RIGOBOT_HOST}/v1/auth/me/token?breathecode_token=${breathecodeToken}`
|
22
16
|
const rigoResp = await fetch(rigoUrl)
|
@@ -80,7 +74,7 @@ const login4Geeks = async (loginInfo: LoginInfo) => {
|
|
80
74
|
return returns
|
81
75
|
}
|
82
76
|
|
83
|
-
const loginWithToken = async (token: string) => {
|
77
|
+
export const loginWithToken = async (token: string) => {
|
84
78
|
const rigoJson = await getRigobotJSON(token)
|
85
79
|
|
86
80
|
const user = await validateUser(token)
|
@@ -198,7 +192,7 @@ export default function Login({ onFinish }: { onFinish: () => void }) {
|
|
198
192
|
|
199
193
|
<button
|
200
194
|
onClick={redirectGithub}
|
201
|
-
className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4"
|
195
|
+
className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4 cursor-pointer"
|
202
196
|
>
|
203
197
|
{SVGS.github}
|
204
198
|
LOGIN WITH GITHUB
|
@@ -227,14 +221,14 @@ export default function Login({ onFinish }: { onFinish: () => void }) {
|
|
227
221
|
<div className="flex gap-2 mt-4">
|
228
222
|
<button
|
229
223
|
type="submit"
|
230
|
-
className="flex-1 bg-sky-500 text-white py-2 rounded-md font-semibold"
|
224
|
+
className="flex-1 bg-sky-500 text-white py-2 rounded-md font-semibold cursor-pointer "
|
231
225
|
>
|
232
226
|
{isLoading ? "Logging in..." : "Log in"}
|
233
227
|
</button>
|
234
228
|
<button
|
235
229
|
type="button"
|
236
230
|
onClick={() => setShowForm(false)}
|
237
|
-
className="flex-1 border border-sky-500 text-sky-600 py-2 rounded-md font-semibold"
|
231
|
+
className="flex-1 border border-sky-500 text-sky-600 py-2 rounded-md font-semibold cursor-pointer"
|
238
232
|
>
|
239
233
|
Skip
|
240
234
|
</button>
|
@@ -252,7 +246,7 @@ export default function Login({ onFinish }: { onFinish: () => void }) {
|
|
252
246
|
) : (
|
253
247
|
<button
|
254
248
|
onClick={() => setShowForm(true)}
|
255
|
-
className="w-full bg-blue-600 text-white py-2 rounded-md font-semibold"
|
249
|
+
className="w-full bg-blue-600 text-white py-2 rounded-md font-semibold cursor-pointer"
|
256
250
|
>
|
257
251
|
Login with Email
|
258
252
|
</button>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import { RigoLoader } from "./RigoLoader"
|
2
|
+
|
3
|
+
import { SVGS } from "../assets/svgs"
|
4
|
+
|
5
|
+
export type TMessage = {
|
6
|
+
type: "user" | "assistant"
|
7
|
+
content: string
|
8
|
+
}
|
9
|
+
|
10
|
+
export const Message: React.FC<TMessage> = ({ type, content }) => {
|
11
|
+
const isAI = type === "assistant"
|
12
|
+
|
13
|
+
const isLoading = isAI && !content
|
14
|
+
return isLoading ? (
|
15
|
+
<RigoLoader text="Thinking..." svg={SVGS.rigoSoftBlue} />
|
16
|
+
) : (
|
17
|
+
<div
|
18
|
+
className={`flex items-start space-x-2 p-3 rounded-md border ${
|
19
|
+
isAI
|
20
|
+
? "bg-gray-50 border-gray-300 text-gray-800"
|
21
|
+
: "bg-blue-50 border-blue-200 text-blue-900"
|
22
|
+
}`}
|
23
|
+
>
|
24
|
+
<span className="mt-1">{isAI ? SVGS.rigoSoftBlue : SVGS.user}</span>
|
25
|
+
<p className="text-sm leading-relaxed">{content}</p>
|
26
|
+
</div>
|
27
|
+
)
|
28
|
+
}
|