feat: quiz plugin in lesson

This commit is contained in:
Jannat Patel
2024-03-11 09:38:27 +05:30
parent 2126b4f657
commit 83a1b03bb7
10 changed files with 266 additions and 222 deletions

View File

@@ -1,6 +1,11 @@
import { toast } from 'frappe-ui'
import { useDateFormat, useTimeAgo } from '@vueuse/core'
import { BookOpen, Users, TrendingUp, Briefcase } from 'lucide-vue-next'
import { Quiz } from '@/utils/quiz'
import Header from '@editorjs/header'
import Paragraph from '@editorjs/paragraph'
import List from '@editorjs/list'
import Embed from '@editorjs/embed'
export function createToast(options) {
toast({
@@ -64,6 +69,37 @@ export function getFileSize(file_size) {
return value
}
export function getEditorTools() {
return {
header: Header,
quiz: Quiz,
paragraph: {
class: Paragraph,
inlineToolbar: true,
config: {
preserveBlank: true,
},
},
list: List,
embed: {
class: Embed,
config: {
services: {
youtube: true,
vimeo: true,
codepen: true,
slides: {
regex: /https:\/\/docs\.google\.com\/presentation\/d\/e\/([A-Za-z0-9_-]+)\/pub/,
embedUrl:
'https://docs.google.com/presentation/d/e/<%= remote_id %>/embed',
html: "<iframe width='100%' height='300' frameborder='0' allowfullscreen='true'></iframe>",
},
},
},
},
}
}
export function getTimezones() {
return [
'Pacific/Midway',

View File

@@ -0,0 +1,58 @@
import QuizBlock from '@/components/QuizBlock.vue'
import { createApp } from 'vue'
import { usersStore } from '../stores/user'
import translationPlugin from '../translation'
export class Quiz {
static get toolbox() {
return {
title: 'Quiz',
icon: `<img src="/assets/lms/icons/quiz.svg" width="15" height="15">`,
}
}
constructor({ data, api, readOnly }) {
this.data = data
this.readOnly = readOnly
}
static get isReadOnlySupported() {
return true
}
render() {
this.wrapper = document.createElement('div')
if (this.data) {
let renderedQuiz = this.renderQuiz(this.data.quiz)
if (!this.readOnly) {
this.wrapper.innerHTML = renderedQuiz
}
}
return this.wrapper
}
renderQuiz(quiz) {
if (this.readOnly) {
const app = createApp(QuizBlock, {
quiz: quiz, // Pass quiz content as prop
})
app.use(translationPlugin)
const { userResource } = usersStore()
app.provide('$user', userResource)
app.mount(this.wrapper)
return
}
return `<div class='border rounded-md p-10 text-center'>
<span class="font-medium">
Quiz: ${quiz}
</span>
</div>`
}
save(blockContent) {
console.log(blockContent)
return {
quiz: this.data.quiz,
}
}
}

View File

@@ -1,78 +0,0 @@
export default class YouTubeVideo {
constructor({ data }) {
this.data = data
}
static get toolbox() {
return {
title: 'YouTube Video',
icon: `<img src="/assets/lms/icons/video.svg" width="15" height="15">`,
}
}
render() {
this.wrapper = document.createElement('div')
if (this.data && this.data.youtube) {
$(this.wrapper).html(this.render_youtube(this.data.youtube))
} else {
this.render_youtube_dialog()
}
return this.wrapper
}
render_youtube_dialog() {
let me = this
let youtubedialog = new frappe.ui.Dialog({
title: __('YouTube Video'),
fields: [
{
fieldname: 'youtube',
fieldtype: 'Data',
label: __('YouTube Video ID'),
reqd: 1,
},
{
fieldname: 'instructions_section_break',
fieldtype: 'Section Break',
label: __('Instructions:'),
},
{
fieldname: 'instructions',
fieldtype: 'HTML',
label: __('Instructions'),
options: __(
'Enter the YouTube Video ID. The ID is the part of the URL after <code>watch?v=</code>. For example, if the URL is <code>https://www.youtube.com/watch?v=QH2-TGUlwu4</code>, the ID is <code>QH2-TGUlwu4</code>'
),
},
],
primary_action_label: __('Insert'),
primary_action(values) {
youtubedialog.hide()
me.youtube = values.youtube
$(me.wrapper).html(me.render_youtube(values.youtube))
},
})
youtubedialog.show()
}
render_youtube(youtube) {
return `<iframe width="100%" height="400"
src="https://www.youtube.com/embed/${youtube}"
title="YouTube video player"
frameborder="0"
style="border-radius: var(--border-radius-lg); margin: 1rem 0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>`
}
validate(savedData) {
return !savedData.youtube || !savedData.youtube.trim() ? false : true
}
save(block_content) {
return {
youtube: this.data.youtube || this.youtube,
}
}
}