Add subtitle block to user content block form
This commit is contained in:
parent
c3bac02826
commit
1112c6754e
|
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
<content-block
|
<content-block
|
||||||
:content-block="contentBlock"
|
:content-block="contentBlock"
|
||||||
:parent="chapter.id"
|
:parent="chapter"
|
||||||
:edit-mode="editMode"
|
:edit-mode="editMode"
|
||||||
v-for="contentBlock in filteredContentBlocks"
|
v-for="contentBlock in filteredContentBlocks"
|
||||||
:key="contentBlock.id"
|
:key="contentBlock.id"
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
const DocumentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/DocumentForm');
|
const DocumentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/DocumentForm');
|
||||||
const AssignmentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/AssignmentForm');
|
const AssignmentForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/AssignmentForm');
|
||||||
const TextForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/TextForm');
|
const TextForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/TextForm');
|
||||||
|
const SubtitleForm = () => import(/* webpackChunkName: "content-forms" */'@/components/content-forms/SubtitleForm');
|
||||||
|
|
||||||
const CHOOSER = 'content-block-element-chooser-widget';
|
const CHOOSER = 'content-block-element-chooser-widget';
|
||||||
|
|
||||||
|
|
@ -73,6 +74,7 @@
|
||||||
DocumentForm,
|
DocumentForm,
|
||||||
AssignmentForm,
|
AssignmentForm,
|
||||||
TextForm,
|
TextForm,
|
||||||
|
SubtitleForm
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -96,6 +98,12 @@
|
||||||
methods: {
|
methods: {
|
||||||
getType(element) {
|
getType(element) {
|
||||||
switch (element.type) {
|
switch (element.type) {
|
||||||
|
case 'subtitle':
|
||||||
|
return {
|
||||||
|
component: 'subtitle-form',
|
||||||
|
title: 'Untertitel',
|
||||||
|
icon: 'title-icon'
|
||||||
|
};
|
||||||
case 'link_block':
|
case 'link_block':
|
||||||
return {
|
return {
|
||||||
component: 'link-form',
|
component: 'link-form',
|
||||||
|
|
@ -168,6 +176,14 @@
|
||||||
value: Object.assign({}, value),
|
value: Object.assign({}, value),
|
||||||
};
|
};
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case 'subtitle':
|
||||||
|
el = {
|
||||||
|
...el,
|
||||||
|
value: {
|
||||||
|
text: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
break;
|
||||||
case 'text_block':
|
case 'text_block':
|
||||||
el = {
|
el = {
|
||||||
...el,
|
...el,
|
||||||
|
|
|
||||||
|
|
@ -137,31 +137,31 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "@/styles/_variables.scss";
|
@import "~styles/helpers";
|
||||||
|
|
||||||
.content-component {
|
.content-component {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&--bookmarked {
|
&--bookmarked {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
&--subtitle {
|
||||||
|
margin-top: $section-spacing;
|
||||||
|
margin-bottom: $large-spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--section_title {
|
||||||
|
margin-top: $section-spacing;
|
||||||
|
margin-bottom: $large-spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--text_block {
|
||||||
|
margin-bottom: $large-spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--document_block {
|
||||||
|
margin-bottom: $large-spacing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--subtitle {
|
|
||||||
margin-top: $section-spacing;
|
|
||||||
margin-bottom: $large-spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--section_title {
|
|
||||||
margin-top: $section-spacing;
|
|
||||||
margin-bottom: $large-spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--text_block {
|
|
||||||
margin-bottom: $large-spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--document_block {
|
|
||||||
margin-bottom: $large-spacing;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
sanitizedText() {
|
sanitizedText() {
|
||||||
// todo: we can't just sanitize, because there are some elements in there that come from the server
|
// don't need to sanitize the input, server does this
|
||||||
return this.value.text;
|
return this.value.text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,16 @@
|
||||||
:class="{'content-block-element-chooser-widget--no-assignment': hideAssignment}"
|
:class="{'content-block-element-chooser-widget--no-assignment': hideAssignment}"
|
||||||
class="content-block-element-chooser-widget"
|
class="content-block-element-chooser-widget"
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
|
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--subtitle"
|
||||||
|
data-cy="choose-subtitle-widget"
|
||||||
|
@click="changeType('subtitle')"
|
||||||
|
>
|
||||||
|
<title-icon class="content-block-element-chooser-widget__link-icon" />
|
||||||
|
<div class="content-block-element-chooser-widget__link-title">
|
||||||
|
Untertitel
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--link"
|
class="content-block-element-chooser-widget__link content-block-element-chooser-widget__link--link"
|
||||||
data-cy="choose-link-widget"
|
data-cy="choose-link-widget"
|
||||||
|
|
@ -87,6 +97,7 @@
|
||||||
import Checkbox from '@/components/ui/Checkbox';
|
import Checkbox from '@/components/ui/Checkbox';
|
||||||
|
|
||||||
import formElementIcons from '@/components/ui/form-element-icons';
|
import formElementIcons from '@/components/ui/form-element-icons';
|
||||||
|
import TitleIcon from '@/components/icons/TitleIcon';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -103,6 +114,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
TitleIcon,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
...formElementIcons
|
...formElementIcons
|
||||||
},
|
},
|
||||||
|
|
@ -131,8 +143,8 @@
|
||||||
@supports (display: grid) {
|
@supports (display: grid) {
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
grid-template-columns: repeat(6, 1fr);
|
grid-template-columns: repeat(7, 1fr);
|
||||||
-ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
-ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||||
grid-column-gap: 0px;
|
grid-column-gap: 0px;
|
||||||
font-family: $sans-serif-font-family;
|
font-family: $sans-serif-font-family;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<template>
|
||||||
|
<div class="subtitle-form">
|
||||||
|
<input-with-label
|
||||||
|
:value="text"
|
||||||
|
class="subtitle-form__input"
|
||||||
|
data-cy="subtitle-form-input"
|
||||||
|
label="Text"
|
||||||
|
placeholder="z.b. Vor dem Lesen"
|
||||||
|
@input="$emit('change-text', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import InputWithLabel from '@/components/ui/InputWithLabel';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
validator(value) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(value, 'text');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index: {
|
||||||
|
type: Number,
|
||||||
|
default: -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {InputWithLabel},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
text() {
|
||||||
|
return this.value.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import "~styles/helpers";
|
||||||
|
|
||||||
|
.subtitle-form {
|
||||||
|
&__input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
width="50"
|
||||||
|
height="50"
|
||||||
|
viewBox="0 0 50 50"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M40.875 6.50635H9.125C8.96084 6.50634 8.79829 6.53866 8.64663 6.60147C8.49497 6.66429 8.35716 6.75636 8.24109 6.87244C8.12501 6.98851 8.03294 7.12632 7.97013 7.27798C7.90731 7.42964 7.87499 7.59219 7.875 7.75635V13.8828C7.875 14.2143 8.0067 14.5323 8.24112 14.7667C8.47554 15.0011 8.79348 15.1328 9.125 15.1328C9.45652 15.1328 9.77446 15.0011 10.0089 14.7667C10.2433 14.5323 10.375 14.2143 10.375 13.8828V9.00635H23.75V40.9936H18.4312C18.0996 40.9936 17.7817 41.1253 17.5473 41.3598C17.3128 41.5942 17.1812 41.9121 17.1812 42.2436C17.1812 42.5752 17.3128 42.8931 17.5473 43.1275C17.7817 43.3619 18.0996 43.4936 18.4312 43.4936H31.5688C31.9004 43.4936 32.2183 43.3619 32.4527 43.1275C32.6872 42.8931 32.8189 42.5752 32.8189 42.2436C32.8189 41.9121 32.6872 41.5942 32.4527 41.3598C32.2183 41.1253 31.9004 40.9936 31.5688 40.9936H26.25V9.00635H39.625V13.8828C39.625 14.2143 39.7567 14.5323 39.9911 14.7667C40.2255 15.0011 40.5435 15.1328 40.875 15.1328C41.2065 15.1328 41.5245 15.0011 41.7589 14.7667C41.9933 14.5323 42.125 14.2143 42.125 13.8828V7.75635C42.125 7.59219 42.0927 7.42964 42.0299 7.27798C41.9671 7.12632 41.875 6.98851 41.7589 6.87244C41.6428 6.75636 41.505 6.66429 41.3534 6.60147C41.2017 6.53866 41.0392 6.50634 40.875 6.50635V6.50635Z"
|
||||||
|
fill="#333333"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
@ -4,6 +4,7 @@ const ImageIcon = () => import(/* webpackChunkName: "icons" */'@/components/icon
|
||||||
const TextIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/TextIcon');
|
const TextIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/TextIcon');
|
||||||
const SpeechBubbleIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/SpeechBubbleIcon');
|
const SpeechBubbleIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/SpeechBubbleIcon');
|
||||||
const DocumentIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/DocumentIcon');
|
const DocumentIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/DocumentIcon');
|
||||||
|
const TitleIcon = () => import(/* webpackChunkName: "icons" */'@/components/icons/TitleIcon');
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
LinkIcon,
|
LinkIcon,
|
||||||
|
|
@ -11,5 +12,6 @@ export default {
|
||||||
ImageIcon,
|
ImageIcon,
|
||||||
TextIcon,
|
TextIcon,
|
||||||
SpeechBubbleIcon,
|
SpeechBubbleIcon,
|
||||||
DocumentIcon
|
DocumentIcon,
|
||||||
|
TitleIcon
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ export default function (uri, networkErrorCallback) {
|
||||||
return forward(operation);
|
return forward(operation);
|
||||||
});
|
});
|
||||||
|
|
||||||
const errorLink = onError(({networkError, graphQLErrors, forward, operation}) => {
|
const errorLink = onError(({networkError, graphQLErrors}) => {
|
||||||
if (networkError && networkErrorCallback) {
|
if (networkError && networkErrorCallback) {
|
||||||
networkErrorCallback(networkError.statusCode);
|
networkErrorCallback(networkError.statusCode);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ function redirectUsersToOnboarding() {
|
||||||
function networkErrorCallback(statusCode) {
|
function networkErrorCallback(statusCode) {
|
||||||
if (statusCode === 402) {
|
if (statusCode === 402) {
|
||||||
Vue.$log.debug('status code 402, redirecting');
|
Vue.$log.debug('status code 402, redirecting');
|
||||||
router.push({name: 'licenseActivation'}, 0);
|
router.push({name: 'licenseActivation'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ class InputTypes(graphene.Enum):
|
||||||
video_block = 'video_block'
|
video_block = 'video_block'
|
||||||
document_block = 'document_block'
|
document_block = 'document_block'
|
||||||
content_list_item = 'content_list_item'
|
content_list_item = 'content_list_item'
|
||||||
|
subtitle= 'subtitle'
|
||||||
|
|
||||||
|
|
||||||
class ContentElementValueInput(InputObjectType):
|
class ContentElementValueInput(InputObjectType):
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ ALLOWED_BLOCKS = (
|
||||||
'video_block',
|
'video_block',
|
||||||
'assignment',
|
'assignment',
|
||||||
'document_block',
|
'document_block',
|
||||||
'content_list_item'
|
'content_list_item',
|
||||||
|
'subtitle'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -101,6 +102,13 @@ def handle_content_block(content, context=None, module=None, allowed_blocks=ALLO
|
||||||
'value': {
|
'value': {
|
||||||
'url': bleach.clean(content['value']['url'])
|
'url': bleach.clean(content['value']['url'])
|
||||||
}}
|
}}
|
||||||
|
elif content['type'] == 'subtitle':
|
||||||
|
return {
|
||||||
|
'type': 'subtitle',
|
||||||
|
'value': {
|
||||||
|
'text': bleach.clean(content['value']['text'])
|
||||||
|
}
|
||||||
|
}
|
||||||
elif content['type'] == 'content_list_item':
|
elif content['type'] == 'content_list_item':
|
||||||
return {
|
return {
|
||||||
'type': 'content_list_item',
|
'type': 'content_list_item',
|
||||||
|
|
|
||||||
|
|
@ -478,6 +478,7 @@ enum InputTypes {
|
||||||
video_block
|
video_block
|
||||||
document_block
|
document_block
|
||||||
content_list_item
|
content_list_item
|
||||||
|
subtitle
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstrumentBookmarkNode implements Node {
|
type InstrumentBookmarkNode implements Node {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue