Add video block to frontend and backend

This commit is contained in:
Ramon Wenger 2018-09-12 10:27:40 +02:00
parent 4cb5c6ad63
commit 4010b21cce
11 changed files with 147 additions and 36 deletions

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 '';
}
}

View File

@ -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()

View File

@ -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(

View File

@ -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