CLASSROOMIO-T-116: Replace Markdown with WYSIWIG

CLASSROOMIO-T-116: Resolved Feedbacks

CLASSROOMIO-T-116: Replace Markdown with WYSIWIG


Co-authored-by: Tunji Adeyemi <[email protected]>


Merge-request: CLASSROOMIO-MR-52
Merged-by: Best Admin <[email protected]>
This commit is contained in:
tunny17
2023-08-22 11:01:09 +00:00
committed by Space Cloud
parent 32d0198d3d
commit a422f2f290
4 changed files with 86 additions and 64 deletions
@@ -12,12 +12,11 @@
import MachineLearningModel from 'carbon-icons-svelte/lib/MachineLearningModel.svelte'; import MachineLearningModel from 'carbon-icons-svelte/lib/MachineLearningModel.svelte';
import Tabs from '$lib/components/Tabs/index.svelte'; import Tabs from '$lib/components/Tabs/index.svelte';
import TabContent from '$lib/components/TabContent/index.svelte'; import TabContent from '$lib/components/TabContent/index.svelte';
import MarkdownRender from '$lib/components/MarkdownRender/index.svelte';
import Box from '$lib/components/Box/index.svelte'; import Box from '$lib/components/Box/index.svelte';
import EditContent from '$lib/components/EditContent/index.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
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 { import {
lesson, lesson,
lessons, lessons,
@@ -74,7 +73,7 @@
tabs = tabs.map((tab) => { tabs = tabs.map((tab) => {
const badgeValue = const badgeValue =
tab.value === 1 tab.value === 1
? !!note ? note.length > 15
? 1 ? 1
: 0 : 0
: tab.value === 2 : tab.value === 2
@@ -100,8 +99,9 @@
function updateNoteByCompletion(completion) { function updateNoteByCompletion(completion) {
$lesson.materials.note = completion; $lesson.materials.note = completion;
if (textareaRef) { if (textareaRef && textareaRef?.children?.[0]) {
textareaRef.scrollTop = textareaRef.scrollHeight; let qlEditor = textareaRef?.children?.[0];
qlEditor.scrollTop = qlEditor.scrollHeight;
} }
} }
@@ -183,54 +183,55 @@
<slot:fragment slot="content"> <slot:fragment slot="content">
<TabContent value={tabs[0].value} index={currentTab}> <TabContent value={tabs[0].value} index={currentTab}>
{#if mode === MODES.edit} {#if mode === MODES.edit}
<EditContent <div bind:this={aiButtonRef} class="w-full flex flex-row-reverse">
writeLabel="Note" <PrimaryButton
bind:value={$lesson.materials.note} className="flex items-center relative"
placeholder="Start typing your lesson" onClick={() => {
on:change={handleInputChange} openPopover = !openPopover;
bind:textareaRef }}
bind:buttonRef={aiButtonRef} isLoading={$isLoading}
> isDisabled={$isLoading}
<div slot="buttons" class="flex items-center"> variant={VARIANTS.OUTLINED}
<PrimaryButton >
className="flex items-center relative" <MachineLearningModel size={20} class="carbon-icon mr-3" />
onClick={() => { AI
openPopover = !openPopover; <Popover
caret
align="left"
bind:open={openPopover}
on:click:outside={({ detail }) => {
openPopover = aiButtonRef?.contains(detail.target);
}} }}
isLoading={$isLoading}
isDisabled={$isLoading}
variant={VARIANTS.OUTLINED}
> >
<MachineLearningModel size={20} class="carbon-icon mr-3" /> <div class="p-2">
AI <button class={aiButtonClass} on:click={() => callAI('outline')}>
<Popover <ListIcon class="carbon-icon mr-2" />
caret Generate Lesson Outline
align="left" </button>
bind:open={openPopover} <button class={aiButtonClass} on:click={() => callAI('note')}>
on:click:outside={({ detail }) => { <AlignBoxTopLeftIcon class="carbon-icon mr-2" />
openPopover = aiButtonRef?.contains(detail.target); Generate Lesson Note
}} </button>
> <button class={aiButtonClass} on:click={() => callAI('activities')}>
<div class="p-2"> <IbmWatsonKnowledgeStudioIcon class="carbon-icon mr-2" />
<button class={aiButtonClass} on:click={() => callAI('outline')}> Generate Lesson Activities
<ListIcon class="carbon-icon mr-2" /> </button>
Generate Lesson Outline </div>
</button> </Popover>
<button class={aiButtonClass} on:click={() => callAI('note')}> </PrimaryButton>
<AlignBoxTopLeftIcon class="carbon-icon mr-2" /> </div>
Generate Lesson Note
</button> <div class="h-[60vh]">
<button class={aiButtonClass} on:click={() => callAI('activities')}> <TextEditor
<IbmWatsonKnowledgeStudioIcon class="carbon-icon mr-2" /> bind:container={textareaRef}
Generate Lesson Activities bind:content={$lesson.materials.note}
</button> onChange={(c) => ($lesson.materials.note = c)}
</div> />
</Popover> </div>
</PrimaryButton> {:else if $lesson.materials.note.length > 15}
</div> <div>
</EditContent> {@html $lesson.materials.note}
{:else if $lesson.materials.note} </div>
<MarkdownRender content={$lesson.materials.note} />
{:else} {:else}
<Box> <Box>
<div class="flex justify-between flex-col items-center w-96"> <div class="flex justify-between flex-col items-center w-96">
+5 -6
View File
@@ -1,4 +1,5 @@
<script> <script>
import TextEditor from '$lib/components/TextEditor/index.svelte';
import { marked } from 'marked'; import { marked } from 'marked';
import RoleBasedSecurity from '../RoleBasedSecurity/index.svelte'; import RoleBasedSecurity from '../RoleBasedSecurity/index.svelte';
import PageNav from '../PageNav/index.svelte'; import PageNav from '../PageNav/index.svelte';
@@ -41,13 +42,11 @@
<PageBody width="max-w-3xl px-3"> <PageBody width="max-w-3xl px-3">
{#if mode === MODES.edit} {#if mode === MODES.edit}
<EditContent <TextEditor
writeLabel="Note" bind:content={$course.overview}
bind:value={$course.overview} onChange={(c) => {
placeholder="Start typing your lesson" $course.overview = c;
onInputChange={() => {
isDirty = true; isDirty = true;
console.log('input change');
}} }}
/> />
{:else} {:else}
+28 -6
View File
@@ -7,6 +7,7 @@
export let docId; export let docId;
export let placeholder = 'Type something...'; export let placeholder = 'Type something...';
export let errorMessage; export let errorMessage;
export let container;
const settings = { const settings = {
modules: { modules: {
@@ -16,19 +17,18 @@
toolbar: [ toolbar: [
[{ header: [1, 2, 3, false] }], [{ header: [1, 2, 3, false] }],
['bold', 'italic', 'underline', 'strike'], ['bold', 'italic', 'underline', 'strike'],
['link', 'code-block'], ['link', 'code-block']
], ]
}, },
placeholder: 'Type something...', placeholder: 'Type something...',
theme: 'snow', theme: 'snow'
}, }
}, },
theme: 'snow', theme: 'snow',
placeholder, placeholder
}; };
let quill = null; let quill = null;
let container = null;
function resetContent(docId) { function resetContent(docId) {
if (quill && quill.setText) { if (quill && quill.setText) {
@@ -40,6 +40,14 @@
} }
} }
function setQuillHTML(html) {
console.log('outside if');
if (quill) {
console.log('inside if', html);
quill.setHTML(html);
}
}
onMount(async () => { onMount(async () => {
const { default: Quill } = await import('quill'); const { default: Quill } = await import('quill');
@@ -70,6 +78,8 @@
} }
} }
$: setQuillHTML(content);
$: resetContent(docId); $: resetContent(docId);
</script> </script>
@@ -94,4 +104,16 @@
:global(.dark .ql-editor.ql-blank::before) { :global(.dark .ql-editor.ql-blank::before) {
color: #fff; color: #fff;
} }
:global(.ql-editor) {
white-space: normal !important;
}
:global(.ql-editor p),
:global(.ql-editor h1),
:global(.ql-editor h2),
:global(.ql-editor h3),
:global(.ql-editor h4) {
line-height: 2.2;
}
</style> </style>
+1 -1
View File
@@ -29,7 +29,7 @@ export async function POST({ request }) {
messages: [ messages: [
{ {
role: 'user', role: 'user',
content: `Generate a ${instruction[type]} given the course title is "${courseTitle}" and the lesson is "${lessonTitle}". Format in markdown` 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.`
} }
], ],
stream: true stream: true