CLASSROOMIO-T-132: [BUG] WYSIWIG editing has wrong behavior
CLASSROOMIO-T-132: Final test & remove logs CLASSROOMIO-T-132: Merge Fix (Tailwind Styling) CLASSROOMIO-T-132: Merge Fix Try out cl-editor CLASSROOMIO-T-132: Experimental gpttyping + wysiwig implementation Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com> Co-authored-by: Tunji Adeyemi <tunji@digdippa.com> Merge-request: CLASSROOMIO-MR-58 Merged-by: Best Admin <best@digdippa.com>
This commit is contained in:
committed by
Space Cloud
co-authored by
Rotimi Best
Tunji Adeyemi
parent
a3132371a1
commit
6a691d9fbd
@@ -31,6 +31,7 @@
|
|||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
"canvas-confetti": "^1.6.0",
|
"canvas-confetti": "^1.6.0",
|
||||||
|
"cl-editor": "^2.3.0",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"copy-to-clipboard": "^3.3.3",
|
"copy-to-clipboard": "^3.3.3",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<script>
|
||||||
|
import Editor from 'cl-editor/src/Editor.svelte';
|
||||||
|
|
||||||
|
export let html = '';
|
||||||
|
export let editor;
|
||||||
|
|
||||||
|
let colors = [
|
||||||
|
'#000000',
|
||||||
|
'#e60000',
|
||||||
|
'#ff9900',
|
||||||
|
'#ffff00',
|
||||||
|
'#008a00',
|
||||||
|
'#0066cc',
|
||||||
|
'#9933ff',
|
||||||
|
'#ffffff',
|
||||||
|
'#facccc',
|
||||||
|
'#ffebcc',
|
||||||
|
'#ffffcc',
|
||||||
|
'#cce8cc',
|
||||||
|
'#cce0f5',
|
||||||
|
'#ebd6ff',
|
||||||
|
'#bbbbbb',
|
||||||
|
'#f06666',
|
||||||
|
'#ffc266',
|
||||||
|
'#ffff66',
|
||||||
|
'#66b966',
|
||||||
|
'#66a3e0',
|
||||||
|
'#c285ff',
|
||||||
|
'#888888',
|
||||||
|
'#a10000',
|
||||||
|
'#b26b00',
|
||||||
|
'#b2b200',
|
||||||
|
'#006100',
|
||||||
|
'#0047b2',
|
||||||
|
'#6b24b2',
|
||||||
|
'#444444',
|
||||||
|
'#5c0000',
|
||||||
|
'#663d00',
|
||||||
|
'#666600',
|
||||||
|
'#003700',
|
||||||
|
'#002966',
|
||||||
|
'#3d1466'
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Editor bind:this={editor} {html} {colors} on:change={(evt) => (html = evt.detail)} />
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
||||||
import TextField from '$lib/components/Form/TextField.svelte';
|
import TextField from '$lib/components/Form/TextField.svelte';
|
||||||
import TextEditor from '$lib/components/TextEditor/index.svelte';
|
import TextEditor from '$lib/components/TextEditor/index.svelte';
|
||||||
|
// import ClEditor from '$lib/components/ClEditor/index.svelte';
|
||||||
import {
|
import {
|
||||||
lesson,
|
lesson,
|
||||||
lessons,
|
lessons,
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
import VideoUploader from '$lib/components/Course/components/Lesson/Materials/Video/Index.svelte';
|
import VideoUploader from '$lib/components/Course/components/Lesson/Materials/Video/Index.svelte';
|
||||||
import { course } from '$lib/components/Course/store';
|
import { course } from '$lib/components/Course/store';
|
||||||
import * as CONSTANTS from './constants';
|
import * as CONSTANTS from './constants';
|
||||||
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
export let mode = MODES.view;
|
export let mode = MODES.view;
|
||||||
export let prevMode = '';
|
export let prevMode = '';
|
||||||
@@ -61,6 +63,14 @@
|
|||||||
handleUpdateLessonMaterials(_lesson, lessonId);
|
handleUpdateLessonMaterials(_lesson, lessonId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isNoteEmpty(note) {
|
||||||
|
if (!note || typeof note !== 'string') return true;
|
||||||
|
if (!note.trim()) return true;
|
||||||
|
if (note.trim() === '<p><br></p>') return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
function handleSave(prevMode: string) {
|
function handleSave(prevMode: string) {
|
||||||
if (prevMode === MODES.edit) {
|
if (prevMode === MODES.edit) {
|
||||||
saveLesson();
|
saveLesson();
|
||||||
@@ -71,19 +81,15 @@
|
|||||||
const { slide_url, videos, note } = materials;
|
const { slide_url, videos, note } = materials;
|
||||||
|
|
||||||
tabs = tabs.map((tab) => {
|
tabs = tabs.map((tab) => {
|
||||||
const badgeValue =
|
let badgeValue = 0;
|
||||||
tab.value === 1
|
|
||||||
? note?.length > 15
|
|
||||||
? 1
|
|
||||||
: 0
|
|
||||||
: tab.value === 2
|
|
||||||
? !!slide_url
|
|
||||||
? 1
|
|
||||||
: 0
|
|
||||||
: Array.isArray(videos)
|
|
||||||
? videos.length
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
|
if (tab.value === 1 && !isNoteEmpty(note)) {
|
||||||
|
badgeValue = 1;
|
||||||
|
} else if (tab.value === 2 && !!slide_url) {
|
||||||
|
badgeValue = 1;
|
||||||
|
} else if (tab.value === 3 && !isEmpty(videos)) {
|
||||||
|
badgeValue = 1;
|
||||||
|
}
|
||||||
tab.badgeValue = badgeValue;
|
tab.badgeValue = badgeValue;
|
||||||
return tab;
|
return tab;
|
||||||
});
|
});
|
||||||
@@ -227,8 +233,9 @@
|
|||||||
bind:content={$lesson.materials.note}
|
bind:content={$lesson.materials.note}
|
||||||
onChange={(c) => ($lesson.materials.note = c)}
|
onChange={(c) => ($lesson.materials.note = c)}
|
||||||
/>
|
/>
|
||||||
|
<!-- <ClEditor bind:html={$lesson.materials.note} /> -->
|
||||||
</div>
|
</div>
|
||||||
{:else if $lesson.materials?.note?.length > 15}
|
{:else if !isNoteEmpty($lesson.materials?.note)}
|
||||||
<article class="preview prose prose-sm sm:prose p-2">
|
<article class="preview prose prose-sm sm:prose p-2">
|
||||||
{@html $lesson.materials.note}
|
{@html $lesson.materials.note}
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
let quill = null;
|
let quill = null;
|
||||||
|
let isUserTyping = false;
|
||||||
|
|
||||||
function resetContent(docId) {
|
function resetContent(docId) {
|
||||||
if (quill && quill.setText) {
|
if (quill && quill.setText) {
|
||||||
@@ -64,6 +65,16 @@
|
|||||||
quill.on('text-change', function () {
|
quill.on('text-change', function () {
|
||||||
onChange(quill.getHTML());
|
onChange(quill.getHTML());
|
||||||
});
|
});
|
||||||
|
quill.getModule('toolbar').container.addEventListener('mousedown', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
isUserTyping = true;
|
||||||
|
});
|
||||||
|
quill.root.addEventListener('focus', () => {
|
||||||
|
isUserTyping = true;
|
||||||
|
});
|
||||||
|
quill.root.addEventListener('blur', () => {
|
||||||
|
isUserTyping = false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
@@ -76,7 +87,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: setQuillHTML(content);
|
$: if (!isUserTyping) {
|
||||||
|
setQuillHTML(content);
|
||||||
|
}
|
||||||
|
|
||||||
$: resetContent(docId);
|
$: resetContent(docId);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -22,19 +22,16 @@ const instruction = {
|
|||||||
export async function POST({ request }) {
|
export async function POST({ request }) {
|
||||||
const { prompt } = await request.json();
|
const { prompt } = await request.json();
|
||||||
const { courseTitle, lessonTitle, type } = prompt;
|
const { courseTitle, lessonTitle, type } = prompt;
|
||||||
console.log('prompt', prompt);
|
|
||||||
console.time('debugOpenAi');
|
|
||||||
const response = await openai.createChatCompletion({
|
const response = await openai.createChatCompletion({
|
||||||
model: 'gpt-3.5-turbo',
|
model: 'gpt-3.5-turbo',
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: `Generate a ${instruction[type]} given the course title is "${courseTitle}" and the lesson is "${lessonTitle}". Format in HTML without any styling, don't include the title of the course and title of the lesson in the result & make sure the content is well detailed.`
|
content: `Generate a ${instruction[type]} given the course title is "${courseTitle}" and the lesson is "${lessonTitle}". Format in HTML without any styling, no ul, ol or li tags, don't include the title of the course and title of the lesson in the result & make sure the content is well detailed.`
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
stream: true
|
stream: true
|
||||||
});
|
});
|
||||||
console.timeEnd('debugOpenAi');
|
|
||||||
// Convert the response into a friendly text-stream
|
// Convert the response into a friendly text-stream
|
||||||
const stream = OpenAIStream(response);
|
const stream = OpenAIStream(response);
|
||||||
// Respond with the stream
|
// Respond with the stream
|
||||||
|
|||||||
Reference in New Issue
Block a user