Add video block to frontend and backend
This commit is contained in:
parent
4cb5c6ad63
commit
4010b21cce
|
|
@ -23,11 +23,12 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import TextBlock from '@/components/content-blocks/TextBlock.vue';
|
||||
import BasicKnowledgeWidget from '@/components/content-blocks/BasicKnowledgeWidget.vue';
|
||||
import Task from '@/components/content-blocks/Task.vue';
|
||||
import ImageBlock from '@/components/content-blocks/ImageBlock.vue';
|
||||
import StudentEntry from '@/components/content-blocks/StudentEntry.vue';
|
||||
import TextBlock from '@/components/content-blocks/TextBlock';
|
||||
import BasicKnowledgeWidget from '@/components/content-blocks/BasicKnowledgeWidget';
|
||||
import Task from '@/components/content-blocks/Task';
|
||||
import ImageBlock from '@/components/content-blocks/ImageBlock';
|
||||
import VideoBlock from '@/components/content-blocks/VideoBlock';
|
||||
import StudentEntry from '@/components/content-blocks/StudentEntry';
|
||||
import AddContentBlockButton from '@/components/AddContentBlockButton';
|
||||
import EyeIcon from '@/components/icons/EyeIcon';
|
||||
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
'basic_knowledge': BasicKnowledgeWidget,
|
||||
'student_entry': StudentEntry,
|
||||
'image_block': ImageBlock,
|
||||
'video_block': VideoBlock,
|
||||
Task,
|
||||
AddContentBlockButton,
|
||||
EyeIcon
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import ContentBlockChooserWidget from '@/components/ContentBlockChooserWidget';
|
||||
import ContentBlockChooserWidget from '@/components/content-forms/ContentBlockChooserWidget';
|
||||
import ContentBlockTitleInput from '@/components/ContentBlockTitleInput';
|
||||
import AddContentElement from '@/components/AddContentElement';
|
||||
import LinkForm from '@/components/content-forms/LinkForm';
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
switch (element.type) {
|
||||
case 'link':
|
||||
return 'link-form';
|
||||
case 'video':
|
||||
case 'video_block':
|
||||
return 'video-form';
|
||||
case 'image':
|
||||
return 'image-form';
|
||||
|
|
@ -124,6 +124,12 @@
|
|||
url: ''
|
||||
};
|
||||
break;
|
||||
case 'video_block':
|
||||
el = {
|
||||
...el,
|
||||
url: ''
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
this.elements.splice(index, 1, el);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="video-block">
|
||||
<youtube-embed v-if="isYoutube" :url="value.url"></youtube-embed>
|
||||
<vimeo-embed v-if="isVimeo" :url="value.url"></vimeo-embed>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import YoutubeEmbed from '@/components/videos/YoutubeEmbed';
|
||||
import VimeoEmbed from '@/components/videos/VimeoEmbed';
|
||||
import {isVimeoUrl, isYoutubeUrl} from '@/helpers/video';
|
||||
|
||||
export default {
|
||||
props: ['value'],
|
||||
|
||||
components: {
|
||||
YoutubeEmbed,
|
||||
VimeoEmbed
|
||||
},
|
||||
|
||||
computed: {
|
||||
isYoutube() {
|
||||
return isYoutubeUrl(this.value.url);
|
||||
},
|
||||
isVimeo() {
|
||||
return isVimeoUrl(this.value.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.video-block {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<link-icon class="content-block-chooser-widget__link-icon"></link-icon>
|
||||
<div class="content-block-chooser-widget__link-title">Link</div>
|
||||
</div>
|
||||
<div class="content-block-chooser-widget__link" v-on:click="$emit('change-type', index, 'video')">
|
||||
<div class="content-block-chooser-widget__link" v-on:click="$emit('change-type', index, 'video_block')">
|
||||
<video-icon class="content-block-chooser-widget__link-icon"></video-icon>
|
||||
<div class="content-block-chooser-widget__link-title">Video</div>
|
||||
</div>
|
||||
|
|
@ -15,14 +15,10 @@
|
|||
</div>
|
||||
|
||||
<div v-if="isYoutube">
|
||||
<iframe id="ytplayer" type="text/html"
|
||||
rel="0"
|
||||
:src="`https://www.youtube.com/embed/${videoId}`"
|
||||
frameborder="0"></iframe>
|
||||
<youtube-embed :url="url"></youtube-embed>
|
||||
</div>
|
||||
<div v-if="isVimeo">
|
||||
<iframe :src="`https://player.vimeo.com/video/${videoId}`" frameborder="0"
|
||||
webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
<vimeo-embed :url="url"></vimeo-embed>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -30,32 +26,25 @@
|
|||
|
||||
<script>
|
||||
import InfoIcon from '@/components/icons/InfoIcon';
|
||||
|
||||
const YOUTUBE = /^(?:https:\/\/)?(?:www.)?youtube.com\/watch\?v=([a-zA-Z0-9]*)$/;
|
||||
const VIMEO = /^(?:https:\/\/)?(?:www.)?vimeo.com\/([a-zA-Z0-9]*)$/;
|
||||
import YoutubeEmbed from '@/components/videos/YoutubeEmbed';
|
||||
import VimeoEmbed from '@/components/videos/VimeoEmbed';
|
||||
import {isVimeoUrl, isYoutubeUrl} from '@/helpers/video';
|
||||
|
||||
export default {
|
||||
props: ['url', 'index'],
|
||||
|
||||
components: {
|
||||
InfoIcon
|
||||
InfoIcon,
|
||||
YoutubeEmbed,
|
||||
VimeoEmbed
|
||||
},
|
||||
|
||||
computed: {
|
||||
isYoutube() {
|
||||
return YOUTUBE.test(this.url);
|
||||
return isYoutubeUrl(this.url);
|
||||
},
|
||||
isVimeo() {
|
||||
return VIMEO.test(this.url);
|
||||
},
|
||||
videoId() {
|
||||
if (this.isYoutube) {
|
||||
return YOUTUBE.exec(this.url)[1];
|
||||
} else if (this.isVimeo) {
|
||||
return VIMEO.exec(this.url)[1];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
return isVimeoUrl(this.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,9 +84,5 @@
|
|||
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<iframe class="vimeo-embed" :src="`https://player.vimeo.com/video/${videoId}`" frameborder="0"
|
||||
webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getVideoId} from '@/helpers/video';
|
||||
|
||||
export default {
|
||||
props: ['url'],
|
||||
|
||||
computed: {
|
||||
videoId() {
|
||||
return getVideoId(this.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.vimeo-embed {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<iframe class="youtube-embed" id="ytplayer" type="text/html"
|
||||
rel="0"
|
||||
:src="`https://www.youtube.com/embed/${videoId}`"
|
||||
frameborder="0"></iframe>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getVideoId} from '@/helpers/video';
|
||||
|
||||
export default {
|
||||
props: ['url'],
|
||||
|
||||
computed: {
|
||||
videoId() {
|
||||
return getVideoId(this.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.youtube-embed {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
const YOUTUBE = /^(?:https:\/\/)?(?:www.)?youtube.com\/watch\?v=([a-zA-Z0-9_-]{11})$/;
|
||||
const VIMEO = /^(?:https:\/\/)?(?:www.)?vimeo.com\/([a-zA-Z0-9]*)$/;
|
||||
|
||||
export function isYoutubeUrl(url) {
|
||||
return YOUTUBE.test(url);
|
||||
}
|
||||
|
||||
export function isVimeoUrl(url) {
|
||||
return VIMEO.test(url);
|
||||
}
|
||||
|
||||
export function getVideoId(url) {
|
||||
if (isYoutubeUrl(url)) {
|
||||
return YOUTUBE.exec(url)[1];
|
||||
} else if (isVimeoUrl(url)) {
|
||||
return VIMEO.exec(url)[1];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
@ -31,6 +31,11 @@ class StudentEntryBlock(blocks.StructBlock):
|
|||
task_text = blocks.RichTextBlock()
|
||||
|
||||
|
||||
# 'video_block'
|
||||
class VideoBlock(blocks.StructBlock):
|
||||
url = blocks.URLBlock()
|
||||
|
||||
|
||||
# 'text_block' 'task' 'basic_knowledge' 'student_entry' 'image_block'
|
||||
#
|
||||
# url = blocks.URLBlock()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList,
|
|||
from wagtail.core.fields import StreamField
|
||||
from wagtail.images.blocks import ImageChooserBlock
|
||||
|
||||
from book.blocks import TextBlock, BasicKnowledgeBlock, StudentEntryBlock, LinkBlock
|
||||
from book.blocks import TextBlock, BasicKnowledgeBlock, StudentEntryBlock, LinkBlock, VideoBlock
|
||||
from core.wagtail_utils import StrictHierarchyPage
|
||||
from user.models import UserGroup
|
||||
|
||||
|
|
@ -35,7 +35,8 @@ class ContentBlock(StrictHierarchyPage):
|
|||
('student_entry', StudentEntryBlock(icon='download')),
|
||||
('image_block', ImageChooserBlock(icon='image')),
|
||||
('link_block', LinkBlock(icon='link')),
|
||||
('task', TextBlock(icon='tick'))
|
||||
('task', TextBlock(icon='tick')),
|
||||
('video_block', VideoBlock(icon='media')),
|
||||
], null=True, blank=True)
|
||||
|
||||
type = models.CharField(
|
||||
|
|
|
|||
|
|
@ -31,7 +31,11 @@ def handle_content_blocks(content_data):
|
|||
elif content['type'] == 'task':
|
||||
pass
|
||||
elif content['type'] == 'video_block':
|
||||
pass
|
||||
new_contents.append({
|
||||
'type': 'video_block',
|
||||
'value': {
|
||||
'url': bleach.clean(content['url'])
|
||||
}})
|
||||
elif content['type'] == 'document_block':
|
||||
pass
|
||||
return new_contents
|
||||
|
|
|
|||
Loading…
Reference in New Issue