example with uploadcare
This commit is contained in:
parent
ef48f5afb6
commit
b8b09b1af3
|
|
@ -8,6 +8,14 @@
|
||||||
<link href='https://fonts.googleapis.com/css?family=Material+Icons' rel="stylesheet" type="text/css">
|
<link href='https://fonts.googleapis.com/css?family=Material+Icons' rel="stylesheet" type="text/css">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500,800" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500,800" rel="stylesheet">
|
||||||
<link href="https://use.typekit.net/tck7ptw.css" rel="stylesheet">
|
<link href="https://use.typekit.net/tck7ptw.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
UPLOADCARE_LOCALE = "de";
|
||||||
|
UPLOADCARE_TABS = "file url facebook gdrive gphotos dropbox instagram evernote flickr skydrive";
|
||||||
|
UPLOADCARE_PUBLIC_KEY = "ad89e9f42d4f5532d176";
|
||||||
|
</script>
|
||||||
|
<script charset="utf-8" src="//ucarecdn.com/libs/widget/3.6.0/uploadcare.full.min.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
import BasicKnowledgeWidget from '@/components/content-blocks/BasicKnowledgeWidget';
|
import BasicKnowledgeWidget from '@/components/content-blocks/BasicKnowledgeWidget';
|
||||||
import Task from '@/components/content-blocks/Task';
|
import Task from '@/components/content-blocks/Task';
|
||||||
import ImageBlock from '@/components/content-blocks/ImageBlock';
|
import ImageBlock from '@/components/content-blocks/ImageBlock';
|
||||||
|
import ImageUrlBlock from '@/components/content-blocks/ImageUrlBlock';
|
||||||
import VideoBlock from '@/components/content-blocks/VideoBlock';
|
import VideoBlock from '@/components/content-blocks/VideoBlock';
|
||||||
import LinkBlock from '@/components/content-blocks/LinkBlock';
|
import LinkBlock from '@/components/content-blocks/LinkBlock';
|
||||||
import DocumentBlock from '@/components/content-blocks/DocumentBlock';
|
import DocumentBlock from '@/components/content-blocks/DocumentBlock';
|
||||||
|
|
@ -53,6 +54,7 @@
|
||||||
'basic_knowledge': BasicKnowledgeWidget,
|
'basic_knowledge': BasicKnowledgeWidget,
|
||||||
'student_entry': StudentEntry,
|
'student_entry': StudentEntry,
|
||||||
'image_block': ImageBlock,
|
'image_block': ImageBlock,
|
||||||
|
'image_url_block': ImageUrlBlock,
|
||||||
'video_block': VideoBlock,
|
'video_block': VideoBlock,
|
||||||
'link_block': LinkBlock,
|
'link_block': LinkBlock,
|
||||||
'document_block': DocumentBlock,
|
'document_block': DocumentBlock,
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
v-on:link-change-text="changeLinkText"
|
v-on:link-change-text="changeLinkText"
|
||||||
v-on:text-change-value="changeTextValue"
|
v-on:text-change-value="changeTextValue"
|
||||||
v-on:document-change-url="changeDocumentUrl"
|
v-on:document-change-url="changeDocumentUrl"
|
||||||
|
v-on:image-change-url="changeImageUrl"
|
||||||
v-on:video-change-url="changeVideoUrl">
|
v-on:video-change-url="changeVideoUrl">
|
||||||
</component>
|
</component>
|
||||||
<a class="content-block-form__remove" v-on:click="removeElement(index)">
|
<a class="content-block-form__remove" v-on:click="removeElement(index)">
|
||||||
|
|
@ -81,7 +82,7 @@
|
||||||
return 'link-form';
|
return 'link-form';
|
||||||
case 'video_block':
|
case 'video_block':
|
||||||
return 'video-form';
|
return 'video-form';
|
||||||
case 'image_block':
|
case 'image_url_block':
|
||||||
return 'image-form';
|
return 'image-form';
|
||||||
case 'text_block':
|
case 'text_block':
|
||||||
return 'text-form';
|
return 'text-form';
|
||||||
|
|
@ -112,6 +113,9 @@
|
||||||
changeVideoUrl(value, index) {
|
changeVideoUrl(value, index) {
|
||||||
this._updateProperty(value, index, 'url')
|
this._updateProperty(value, index, 'url')
|
||||||
},
|
},
|
||||||
|
changeImageUrl(value, index) {
|
||||||
|
this._updateProperty(value, index, 'url')
|
||||||
|
},
|
||||||
changeDocumentUrl(value, index) {
|
changeDocumentUrl(value, index) {
|
||||||
this._updateProperty(value, index, 'url')
|
this._updateProperty(value, index, 'url')
|
||||||
},
|
},
|
||||||
|
|
@ -167,6 +171,12 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case 'image_url_block':
|
||||||
|
el = {
|
||||||
|
...el,
|
||||||
|
url: ''
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.localContentBlock.contents.splice(index, 1, el);
|
this.localContentBlock.contents.splice(index, 1, el);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<template>
|
||||||
|
<img :src="value.url" alt="" class="image-block">
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: ['value']
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.image-block {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
border-radius: 13px;
|
||||||
|
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<video-icon class="content-block-element-chooser-widget__link-icon"></video-icon>
|
<video-icon class="content-block-element-chooser-widget__link-icon"></video-icon>
|
||||||
<div class="content-block-element-chooser-widget__link-title">Video</div>
|
<div class="content-block-element-chooser-widget__link-title">Video</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-block-element-chooser-widget__link" v-on:click="$emit('change-type', index, 'image_block')">
|
<div class="content-block-element-chooser-widget__link" v-on:click="$emit('change-type', index, 'image_url_block')">
|
||||||
<image-icon class="content-block-element-chooser-widget__link-icon"></image-icon>
|
<image-icon class="content-block-element-chooser-widget__link-icon"></image-icon>
|
||||||
<div class="content-block-element-chooser-widget__link-title">Bild</div>
|
<div class="content-block-element-chooser-widget__link-title">Bild</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,26 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="image-form">
|
<div class="image-form">
|
||||||
<input id="image-input" type="file" class="image-form__file-input">
|
<input type="hidden" ref="widget">
|
||||||
<label class="image-form__button" for="image-input">Bild vom Computer hochladen</label>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import uploadcare from 'uploadcare-widget';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['url', 'index'],
|
||||||
|
mounted() {
|
||||||
|
console.log('ImageForm mounted');
|
||||||
|
console.log(this.$refs);
|
||||||
|
const widget = uploadcare.Widget(this.$refs.widget);
|
||||||
|
|
||||||
|
widget.onUploadComplete(info => {
|
||||||
|
console.log(info);
|
||||||
|
console.log(info.cdnUrl);
|
||||||
|
this.$emit('link-change-url', info.cdnUrl, this.index)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
||||||
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
|
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
|
||||||
},
|
},
|
||||||
|
"jquery": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
|
||||||
|
},
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.10.5",
|
"version": "0.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
||||||
|
|
@ -44,6 +49,14 @@
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-3.1.1.tgz",
|
||||||
"integrity": "sha512-syDl3htvM56w0HC0PTVA5jEEknOCJ3dWgWGDuaEtQUno8ORDCfZQbm12RzfWO3AC3YhWDoP61dlgmo8Z05Y97g=="
|
"integrity": "sha512-syDl3htvM56w0HC0PTVA5jEEknOCJ3dWgWGDuaEtQUno8ORDCfZQbm12RzfWO3AC3YhWDoP61dlgmo8Z05Y97g=="
|
||||||
|
},
|
||||||
|
"uploadcare-widget": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uploadcare-widget/-/uploadcare-widget-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-QWvZtPG35ndZJfNxKSu+rrzgIPK+UhO4KzWntP9zfJBvaT1xdbIIF/OMYBhNFG5dbw5j7qFIS2SJvtZZAK9rfw==",
|
||||||
|
"requires": {
|
||||||
|
"jquery": ">=1.10.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"unfetch": "^3.0.0"
|
"unfetch": "^3.0.0",
|
||||||
|
"uploadcare-widget": "3.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Generated by Django 2.0.6 on 2018-09-18 16:05
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
import wagtail.core.blocks
|
||||||
|
import wagtail.core.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('book', '0002_auto_20180913_0738'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='contentblock',
|
||||||
|
name='contents',
|
||||||
|
field=wagtail.core.fields.StreamField([('text_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock())], icon='doc-full')), ('basic_knowledge', wagtail.core.blocks.StructBlock([('description', wagtail.core.blocks.RichTextBlock()), ('url', wagtail.core.blocks.URLBlock())], icon='placeholder')), ('student_entry', wagtail.core.blocks.StructBlock([('task_text', wagtail.core.blocks.RichTextBlock())], icon='download')), ('image_block', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.RichTextBlock()), ('url', wagtail.core.blocks.URLBlock())], icon='image')), ('link_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock()), ('url', wagtail.core.blocks.URLBlock())], icon='link')), ('task', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock())], icon='tick')), ('video_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())], icon='media')), ('document_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())], icon='doc-full'))], blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -5,7 +5,8 @@ from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList,
|
||||||
from wagtail.core.fields import StreamField
|
from wagtail.core.fields import StreamField
|
||||||
from wagtail.images.blocks import ImageChooserBlock
|
from wagtail.images.blocks import ImageChooserBlock
|
||||||
|
|
||||||
from book.blocks import TextBlock, BasicKnowledgeBlock, StudentEntryBlock, LinkBlock, VideoBlock, DocumentBlock
|
from book.blocks import TextBlock, BasicKnowledgeBlock, StudentEntryBlock, LinkBlock, VideoBlock, DocumentBlock, \
|
||||||
|
ImageUrlBlock
|
||||||
from core.wagtail_utils import StrictHierarchyPage
|
from core.wagtail_utils import StrictHierarchyPage
|
||||||
from user.models import UserGroup
|
from user.models import UserGroup
|
||||||
|
|
||||||
|
|
@ -36,6 +37,7 @@ class ContentBlock(StrictHierarchyPage):
|
||||||
('basic_knowledge', BasicKnowledgeBlock(icon='placeholder')),
|
('basic_knowledge', BasicKnowledgeBlock(icon='placeholder')),
|
||||||
('student_entry', StudentEntryBlock(icon='download')),
|
('student_entry', StudentEntryBlock(icon='download')),
|
||||||
('image_block', ImageChooserBlock(icon='image')),
|
('image_block', ImageChooserBlock(icon='image')),
|
||||||
|
('image_url_block', ImageUrlBlock(icon='image')),
|
||||||
('link_block', LinkBlock(icon='link')),
|
('link_block', LinkBlock(icon='link')),
|
||||||
('task', TextBlock(icon='tick')),
|
('task', TextBlock(icon='tick')),
|
||||||
('video_block', VideoBlock(icon='media')),
|
('video_block', VideoBlock(icon='media')),
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ class InputTypes(graphene.Enum):
|
||||||
# basic_knowledge = 'basic_knowledge' # probably won't be using this over the API
|
# basic_knowledge = 'basic_knowledge' # probably won't be using this over the API
|
||||||
student_entry = 'student_entry'
|
student_entry = 'student_entry'
|
||||||
image_block = 'image_block'
|
image_block = 'image_block'
|
||||||
|
image_url_block = 'image_url_block'
|
||||||
link_block = 'link_block'
|
link_block = 'link_block'
|
||||||
task = 'task'
|
task = 'task'
|
||||||
video_block = 'video_block'
|
video_block = 'video_block'
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,12 @@ def handle_content_blocks(content_data):
|
||||||
}})
|
}})
|
||||||
elif content['type'] == 'student_entry':
|
elif content['type'] == 'student_entry':
|
||||||
pass
|
pass
|
||||||
elif content['type'] == 'image_block':
|
elif content['type'] == 'image_url_block':
|
||||||
pass
|
new_contents.append({
|
||||||
|
'type': 'image_url_block',
|
||||||
|
'value': {
|
||||||
|
'url': bleach.clean(content['url'])
|
||||||
|
}})
|
||||||
elif content['type'] == 'link_block':
|
elif content['type'] == 'link_block':
|
||||||
new_contents.append({
|
new_contents.append({
|
||||||
'type': 'link_block',
|
'type': 'link_block',
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
import io
|
|
||||||
import os
|
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from graphene.test import Client
|
from graphene.test import Client
|
||||||
from graphql_relay import to_global_id
|
from graphql_relay import to_global_id
|
||||||
|
|
||||||
|
|
@ -11,8 +7,6 @@ from api.utils import get_graphql_mutation, get_object
|
||||||
from book.factories import ContentBlockFactory
|
from book.factories import ContentBlockFactory
|
||||||
from book.models import ContentBlock
|
from book.models import ContentBlock
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
|
|
||||||
|
|
||||||
class NewContentBlockMutationTest(TestCase):
|
class NewContentBlockMutationTest(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
@ -52,3 +46,33 @@ class NewContentBlockMutationTest(TestCase):
|
||||||
content_block_page = get_object(ContentBlock, id)
|
content_block_page = get_object(ContentBlock, id)
|
||||||
|
|
||||||
self.assertEqual(content_block_page.title, title)
|
self.assertEqual(content_block_page.title, title)
|
||||||
|
|
||||||
|
def test_addNewContentBlock_withImageUrlBlock(self):
|
||||||
|
self.assertEqual(ContentBlock.objects.count(), 1)
|
||||||
|
client = Client(schema=schema)
|
||||||
|
|
||||||
|
mutation = get_graphql_mutation('addContentBlock.gql')
|
||||||
|
|
||||||
|
title = "Hello World"
|
||||||
|
|
||||||
|
result = client.execute(mutation, variables={
|
||||||
|
'input': {
|
||||||
|
"contentBlock": {
|
||||||
|
"title": title,
|
||||||
|
"contents": [
|
||||||
|
{
|
||||||
|
"type": "image_url_block",
|
||||||
|
"url": "/test.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"after": self.sibling_id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.assertIsNone(result.get('errors'))
|
||||||
|
self.assertEqual(ContentBlock.objects.count(), 2)
|
||||||
|
|
||||||
|
new_content_block = result.get('data').get('addContentBlock').get('newContentBlock')
|
||||||
|
self.assertEqual(new_content_block.get('title'), title)
|
||||||
|
self.assertEqual(len(new_content_block['contents']), 1)
|
||||||
|
self.assertEqual(new_content_block['contents'], [{'type': 'image_url_block', 'value': {'url': '/test.png'}}])
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue