diff --git a/cypress.config.js b/cypress.config.js index 04ebc494..d93eac9e 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -13,6 +13,6 @@ module.exports = defineConfig({ openMode: 0, }, e2e: { - baseUrl: "http://pyp:8000", + baseUrl: "http://test_site_ui:8000", }, }); diff --git a/cypress/e2e/course_creation.cy.js b/cypress/e2e/course_creation.cy.js index 142b2f13..33f6eee9 100644 --- a/cypress/e2e/course_creation.cy.js +++ b/cypress/e2e/course_creation.cy.js @@ -108,14 +108,11 @@ describe("Course Creation", () => { cy.get("[id^=headlessui-disclosure-panel-").within(() => { cy.get("div").contains("Test Lesson").click(); }); - cy.wait(1000); + cy.wait(3000); // View Lesson cy.url().should("include", "/learn/1-1"); cy.get("div").contains("Test Lesson"); - cy.get("div").contains( - "This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now. " - ); cy.get("video") .should("be.visible") @@ -123,6 +120,10 @@ describe("Course Creation", () => { .invoke("attr", "src") .should("include", "/files/Youtube"); + cy.get("div").contains( + "This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now." + ); + // Add Discussion cy.button("New Question").click(); cy.wait(500); diff --git a/frontend/src/components/AudioBlock.vue b/frontend/src/components/AudioBlock.vue new file mode 100644 index 00000000..36303b7f --- /dev/null +++ b/frontend/src/components/AudioBlock.vue @@ -0,0 +1,137 @@ + + + + diff --git a/frontend/src/components/VideoBlock.vue b/frontend/src/components/VideoBlock.vue new file mode 100644 index 00000000..7a0f463d --- /dev/null +++ b/frontend/src/components/VideoBlock.vue @@ -0,0 +1,178 @@ + + + + diff --git a/frontend/src/stores/user.js b/frontend/src/stores/user.js index 1c1c6c02..6133b8a5 100644 --- a/frontend/src/stores/user.js +++ b/frontend/src/stores/user.js @@ -15,6 +15,7 @@ export const usersStore = defineStore('lms-users', () => { const allUsers = createResource({ url: 'lms.lms.api.get_all_users', cache: ['allUsers'], + auto: true, }) return { diff --git a/frontend/src/utils/customEmbed.js b/frontend/src/utils/customEmbed.js new file mode 100644 index 00000000..9cd297c0 --- /dev/null +++ b/frontend/src/utils/customEmbed.js @@ -0,0 +1,32 @@ +import Embed from '@editorjs/embed' +import VideoBlock from '@/components/VideoBlock.vue' +import { createApp } from 'vue' + +export class CustomEmbed extends Embed { + render() { + const container = super.render() + const { service, source, embed } = this.data + + if (service === 'youtube' || service === 'vimeo') { + // Remove the iframe or existing embed content + container.innerHTML = '' + + // Create a placeholder element for Vue component + const vueContainer = document.createElement('div') + vueContainer.setAttribute('data-service', service) + vueContainer.setAttribute('data-video-id', this.data.source) + + // Append the Vue placeholder + container.appendChild(vueContainer) + console.log(source) + // Mount the Vue component (using a global Vue instance) + const app = createApp(VideoBlock, { + file: source, + type: 'video/youtube', + }) + app.mount(vueContainer) + } + + return container + } +} diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index 59f5856d..19441c33 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -4,12 +4,12 @@ import { Quiz } from '@/utils/quiz' import { Upload } from '@/utils/upload' import Header from '@editorjs/header' import Paragraph from '@editorjs/paragraph' -import Embed from '@editorjs/embed' import { CodeBox } from '@/utils/code' import NestedList from '@editorjs/nested-list' import InlineCode from '@editorjs/inline-code' -import { watch } from 'vue' +import { watch, createApp } from 'vue' import dayjs from '@/utils/dayjs' +import Embed from '@editorjs/embed' export function createToast(options) { toast({ @@ -167,6 +167,7 @@ export function getEditorTools() { youtube: true, vimeo: true, codepen: true, + aparat: true, slides: { regex: /https:\/\/docs\.google\.com\/presentation\/d\/e\/([A-Za-z0-9_-]+)\/pub/, embedUrl: diff --git a/frontend/src/utils/upload.js b/frontend/src/utils/upload.js index fbe607d1..939c3999 100644 --- a/frontend/src/utils/upload.js +++ b/frontend/src/utils/upload.js @@ -1,3 +1,7 @@ +import AudioBlock from '@/components/AudioBlock.vue' +import VideoBlock from '@/components/VideoBlock.vue' +import { createApp } from 'vue' + export class Upload { constructor({ data, api, readOnly }) { this.data = data @@ -10,19 +14,23 @@ export class Upload { render() { this.wrapper = document.createElement('div') - this.wrapper.innerHTML = this.renderUpload(this.data) + this.renderUpload(this.data) return this.wrapper } renderUpload(file) { if (this.isVideo(file.file_type)) { - return `` + const app = createApp(VideoBlock, { + file: file.file_url, + }) + app.mount(this.wrapper) + return } else if (this.isAudio(file.file_type)) { - return `` + const app = createApp(AudioBlock, { + file: file.file_url, + }) + app.mount(this.wrapper) + return } else if (file.file_type == 'pdf') { return `