remotes/origin/hasaccess
Sanasol 8 years ago
parent 19da4b6c29
commit a765836b56
  1. 33
      api/v1/serializers/mixins.py
  2. 19
      apps/content/migrations/0016_auto_20180406_1816.py
  3. 19
      apps/content/migrations/0017_auto_20180406_1847.py
  4. 2
      apps/content/models.py
  5. 6
      apps/course/templates/course/course_edit.html
  6. 2
      apps/course/views.py
  7. 3
      project/urls.py
  8. 96
      web/src/components/CourseRedactor.vue
  9. 2
      web/src/components/LessonRedactor.vue
  10. 13
      web/src/js/modules/api.js

@ -37,7 +37,14 @@ class DispatchContentMixin(object):
image.position = cdata['position'] image.position = cdata['position']
image.title = cdata['title'] image.title = cdata['title']
image.course = course image.course = course
image.img = ImageObject.objects.get(id=cdata['img'])
try:
image_object = ImageObject.objects.get(id=cdata['img'])
image.img = image_object
image.save()
except ImageObject.DoesNotExist:
pass
image.uuid = cdata['uuid'] image.uuid = cdata['uuid']
image.save() image.save()
else: else:
@ -45,16 +52,29 @@ class DispatchContentMixin(object):
position=cdata['position'], position=cdata['position'],
title=cdata['title'], title=cdata['title'],
course=course, course=course,
img=ImageObject.objects.get(id=cdata['img']),
uuid=cdata['uuid'], uuid=cdata['uuid'],
) )
try:
image_object = ImageObject.objects.get(id=cdata['img'])
image.img = image_object
image.save()
except ImageObject.DoesNotExist:
pass
elif ctype == 'image-text': elif ctype == 'image-text':
if 'id' in cdata and cdata['id']: if 'id' in cdata and cdata['id']:
it = ImageText.objects.get(id=cdata['id']) it = ImageText.objects.get(id=cdata['id'])
it.position = cdata['position'] it.position = cdata['position']
it.title = cdata['title'] it.title = cdata['title']
it.course = course it.course = course
it.img = ImageObject.objects.get(id=cdata['img'])
try:
image_object = ImageObject.objects.get(id=cdata['img'])
it.img = image_object
it.save()
except ImageObject.DoesNotExist:
pass
it.txt = cdata['txt'] it.txt = cdata['txt']
it.uuid = cdata['uuid'] it.uuid = cdata['uuid']
it.save() it.save()
@ -63,10 +83,15 @@ class DispatchContentMixin(object):
position=cdata['position'], position=cdata['position'],
title=cdata['title'], title=cdata['title'],
course=course, course=course,
img=ImageObject.objects.get(id=cdata['img']),
txt=cdata['txt'], txt=cdata['txt'],
uuid=cdata['uuid'], uuid=cdata['uuid'],
) )
try:
image_object = ImageObject.objects.get(id=cdata['img'])
it.img = image_object
it.save()
except ImageObject.DoesNotExist:
pass
elif ctype == 'video': elif ctype == 'video':
if 'id' in cdata and cdata['id']: if 'id' in cdata and cdata['id']:
v = Video.objects.get(id=cdata['id']) v = Video.objects.get(id=cdata['id'])

@ -0,0 +1,19 @@
# Generated by Django 2.0.3 on 2018-04-06 18:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('content', '0015_content_uuid'),
]
operations = [
migrations.AlterField(
model_name='image',
name='img',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='content_images', to='content.ImageObject', verbose_name='Объект изображения'),
),
]

@ -0,0 +1,19 @@
# Generated by Django 2.0.3 on 2018-04-06 18:47
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('content', '0016_auto_20180406_1816'),
]
operations = [
migrations.AlterField(
model_name='imagetext',
name='img',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='content_imagetexts', to='content.ImageObject', verbose_name='Объект изображения'),
),
]

@ -52,6 +52,7 @@ class Image(Content):
img = models.ForeignKey( img = models.ForeignKey(
ImageObject, related_name='content_images', ImageObject, related_name='content_images',
verbose_name='Объект изображения', on_delete=models.CASCADE, verbose_name='Объект изображения', on_delete=models.CASCADE,
null=True
) )
@ -63,6 +64,7 @@ class ImageText(Content):
img = models.ForeignKey( img = models.ForeignKey(
ImageObject, related_name='content_imagetexts', ImageObject, related_name='content_imagetexts',
verbose_name='Объект изображения', on_delete=models.CASCADE, verbose_name='Объект изображения', on_delete=models.CASCADE,
null=True
) )
txt = models.TextField('Текст', default='') txt = models.TextField('Текст', default='')

@ -14,6 +14,6 @@
{% if course and course.id %}:course-id="{{ course.id }}"{% endif %}></course-redactor> {% if course and course.id %}:course-id="{{ course.id }}"{% endif %}></course-redactor>
{% endblock content %} {% endblock content %}
{% block foot %} {% block foot %}
<script type="text/javascript" src="{% static "courseRedactor.js" %}"></script> <script type="text/javascript" src="{% static 'courseRedactor.js' %}"></script>
<link rel="stylesheet" href="{% static "courseRedactor.css" %}" /> <link rel="stylesheet" href="{% static 'courseRedactor.css' %}" />
{% endblock foot %} {% endblock foot %}

@ -155,7 +155,7 @@ class CourseOnModerationView(TemplateView):
class CourseEditView(TemplateView): class CourseEditView(TemplateView):
template_name = 'course/course_edit.html' template_name = 'course/course_edit.html'
def get(self, request, pk=None): def get(self, request, pk=None, lesson=None):
drafts = Course.objects.filter( drafts = Course.objects.filter(
author=request.user, status=Course.DRAFT author=request.user, status=Course.DRAFT
) )

@ -46,6 +46,9 @@ urlpatterns = [
path('author-request/success/', TemplateView.as_view(template_name='user/become-author-success.html'), name='author-request-success'), path('author-request/success/', TemplateView.as_view(template_name='user/become-author-success.html'), name='author-request-success'),
path('courses/', CoursesView.as_view(), name='courses'), path('courses/', CoursesView.as_view(), name='courses'),
path('course/create', CourseEditView.as_view(), name='course_create'), path('course/create', CourseEditView.as_view(), name='course_create'),
path('course/create/lessons', CourseEditView.as_view(), name='course_create'),
path('course/create/lessons/new', CourseEditView.as_view(), name='course_create'),
path('course/create/lessons/edit/<int:lesson>', CourseEditView.as_view(), name='course_create'),
path('course/create/live', CourseLiveEditView.as_view(), name='course_create_live'), path('course/create/live', CourseLiveEditView.as_view(), name='course_create_live'),
path('course/on-moderation', CourseOnModerationView.as_view(), name='course-on-moderation'), path('course/on-moderation', CourseOnModerationView.as_view(), name='course-on-moderation'),
path('course/<int:pk>/', CourseView.as_view(), name='course'), path('course/<int:pk>/', CourseView.as_view(), name='course'),

@ -35,6 +35,18 @@
v-model="course.title"></textarea> v-model="course.title"></textarea>
</div> </div>
</div> </div>
<div class="info__field field field_info"
v-bind:class="{ error: ($v.course.short_description.$dirty || showErrors) && $v.course.short_description.$invalid }">
<div class="field__label">КРАТКО О КУРСЕ</div>
<div class="field__wrap">
<textarea class="field__input"
rows="1"
placeholder="Кратко о курсе"
v-autosize="course.short_description"
@input="$v.course.short_description.$touch()"
v-model="course.short_description"></textarea>
</div>
</div>
</div> </div>
<div class="info__foot" v-if="!live"> <div class="info__foot" v-if="!live">
<div class="info__field field field_info info__field--light" <div class="info__field field field_info info__field--light"
@ -138,25 +150,6 @@
<div class="section"> <div class="section">
<div class="section__center center"> <div class="section__center center">
<div class="kit"> <div class="kit">
<div class="kit__section">
<div class="kit__field field"
v-bind:class="{ error: ($v.course.short_description.$dirty || showErrors) && $v.course.short_description.$invalid }">
<div class="field__wrap">
<textarea class="field__input"
rows="1"
placeholder="Кратко о курсе"
v-autosize="course.short_description"
@input="$v.course.short_description.$touch()"
v-model="course.short_description"></textarea>
</div>
</div>
<block-images
:index="0"
:readOnly="true"
title="Результаты урока"
:images.sync="course.gallery.images"
:access-token="accessToken"/>
</div>
<div v-if="!live" id="course-redactor__nav" class="kit__nav"> <div v-if="!live" id="course-redactor__nav" class="kit__nav">
<button class="kit__btn btn btn_lg" <button class="kit__btn btn btn_lg"
v-bind:class="{ 'btn_stroke': viewSection === 'course', 'btn_gray': viewSection !== 'course' }" v-bind:class="{ 'btn_stroke': viewSection === 'course', 'btn_gray': viewSection !== 'course' }"
@ -323,7 +316,11 @@
lessons: [], lessons: [],
lessonsLoading: false, lessonsLoading: false,
lessonSaving: false, lessonSaving: false,
currentLesson: null, currentLesson: {
title: '',
short_description: '',
content: [],
},
is_adding_block: false, is_adding_block: false,
timeOptions: [ timeOptions: [
{ {
@ -469,9 +466,7 @@
}, },
editLesson(lessonIndex) { editLesson(lessonIndex) {
this.currentLesson = this.lessons[lessonIndex]; this.currentLesson = this.lessons[lessonIndex];
if (this.viewSection !== 'lessons-edit') { history.push("/course/create/lessons/edit/"+this.currentLesson.id);
history.push("/course/create/lessons/new");
}
this.viewSection = 'lessons-edit'; this.viewSection = 'lessons-edit';
}, },
showCourse() { showCourse() {
@ -490,7 +485,6 @@
this.currentLesson = { this.currentLesson = {
title: '', title: '',
short_description: '', short_description: '',
course_id: this.course.id,
content: [], content: [],
}; };
if (this.viewSection !== 'lessons-edit') { if (this.viewSection !== 'lessons-edit') {
@ -513,6 +507,7 @@
onLessonSubmit() { onLessonSubmit() {
this.lessonSaving = true; this.lessonSaving = true;
const currentLessonId = this.currentLesson.id; const currentLessonId = this.currentLesson.id;
this.currentLesson.course_id = this.course.id;
api.saveLesson(this.currentLesson, this.accessToken) api.saveLesson(this.currentLesson, this.accessToken)
.then((response) => { .then((response) => {
this.lessonSaving = false; this.lessonSaving = false;
@ -535,6 +530,7 @@
}); });
}, },
goToLessons() { goToLessons() {
history.push("/course/create/lessons");
this.viewSection = 'lessons'; this.viewSection = 'lessons';
this.$nextTick(() => { this.$nextTick(() => {
const elementTop = $('#course-redactor__nav').position().top - 130; const elementTop = $('#course-redactor__nav').position().top - 130;
@ -543,7 +539,9 @@
}, },
loadCourseDraft() { loadCourseDraft() {
this.courseLoading = true; this.courseLoading = true;
api.getCourseDraft(this.accessToken) let response = api.getCourseDraft(this.accessToken);
response
.then((response) => { .then((response) => {
this.courseLoading = false; this.courseLoading = false;
this.course = api.convertCourseJson(response.data); this.course = api.convertCourseJson(response.data);
@ -555,10 +553,13 @@
this.courseLoading = false; this.courseLoading = false;
console.log('error course loading', err); console.log('error course loading', err);
}); });
return response;
}, },
loadCourse() { loadCourse() {
this.courseLoading = true; this.courseLoading = true;
api.loadCourse(this.courseId, this.accessToken) let response = api.loadCourse(this.courseId, this.accessToken)
response
.then((response) => { .then((response) => {
this.courseLoading = false; this.courseLoading = false;
this.course = api.convertCourseJson(response.data); this.course = api.convertCourseJson(response.data);
@ -570,6 +571,8 @@
this.courseLoading = false; this.courseLoading = false;
console.log('error course loading', err); console.log('error course loading', err);
}); });
return response;
}, },
loadLessons(courseId) { loadLessons(courseId) {
@ -651,22 +654,35 @@
.catch((err) => { .catch((err) => {
this.courseSyncHook = false; this.courseSyncHook = false;
this.courseSaving = false; this.courseSaving = false;
console.error(err);
document.getElementById('course-redactor__saving-status').innerText = 'ОШИБКА';
this.savingTimeout = setTimeout(() => {
document.getElementById('course-redactor__saving-status').innerText = '';
}, 2000);
alert('Произошло что-то страшное: '+err.toString());
}); });
}, 3000); }, 500);
},
updateViewSection(location, action) {
console.log('updateViewSection[action]', action);
if (location.pathname === '/course/create/lessons') {
this.viewSection = 'lessons';
} else if (location.pathname === '/course/create') {
this.viewSection = 'course';
} else if (location.pathname === '/course/create/lessons/new') {
this.viewSection = 'lessons-edit';
} else if (location.pathname.indexOf('/course/create/lessons/edit') !== -1) {
let lessonId = parseInt(location.pathname.split('/').pop());
console.log('lessonId', lessonId, this.lessons.toString());
console.log('lessod edit', this.lessons.find((i)=>{return i.id === lessonId}));
this.currentLesson = this.lessons.find((i)=>{return i.id === lessonId});
this.viewSection = 'lessons-edit';
}
} }
}, },
mounted() { mounted() {
console.log('live', this.live);
// Listen for changes to the current location. // Listen for changes to the current location.
this.unlisten = history.listen((location, action) => { this.unlisten = history.listen(this.updateViewSection);
if (location.pathname === '/course/create/lessons') {
this.viewSection = 'lessons';
} else if (location.pathname === '/course/create') {
this.viewSection = 'course';
} else if (location.pathname === '/course/create/lessons/new') {
this.viewSection = 'lessons-edit';
}
});
api.getCategories(this.accessToken) api.getCategories(this.accessToken)
.then((response) => { .then((response) => {
@ -703,10 +719,12 @@
}); });
if (this.courseId) { if (this.courseId) {
this.loadCourse() this.loadCourse().then(()=>{this.updateViewSection(window.location, 'load')})
} else { } else {
this.loadCourseDraft(); this.loadCourseDraft().then(()=>{this.updateViewSection(window.location, 'load draft')});
} }
// this.updateViewSection(window.location);
}, },
computed: { computed: {
coverBackgroundStyle() { coverBackgroundStyle() {

@ -1,6 +1,6 @@
<template> <template>
<div class="section"> <div class="section">
<div class="section__center center"> <div class="section__center center" v-if="lesson">
<div class="kit"> <div class="kit">
<div class="kit__go go"> <div class="kit__go go">
<a href="#" class="go__item" @click.prevent="goBack"> <a href="#" class="go__item" @click.prevent="goBack">

@ -165,6 +165,7 @@ export const api = {
'position': ++index, 'position': ++index,
'title': block.data.title, 'title': block.data.title,
'txt': block.data.text, 'txt': block.data.text,
'uuid': block.uuid,
} }
} }
} else if (block.type === 'image') { } else if (block.type === 'image') {
@ -175,6 +176,7 @@ export const api = {
'position': ++index, 'position': ++index,
'title': block.data.title, 'title': block.data.title,
'img': block.data.image_id, 'img': block.data.image_id,
'uuid': block.uuid,
} }
} }
} else if (block.type === 'image-text') { } else if (block.type === 'image-text') {
@ -186,6 +188,7 @@ export const api = {
'title': block.data.title, 'title': block.data.title,
'img': block.data.image_id, 'img': block.data.image_id,
'txt': block.data.text, 'txt': block.data.text,
'uuid': block.uuid,
} }
} }
} else if (block.type === 'images') { } else if (block.type === 'images') {
@ -201,6 +204,7 @@ export const api = {
'img': galleryImage.img, 'img': galleryImage.img,
} }
}), }),
'uuid': block.uuid,
} }
} }
} else if (block.type === 'video') { } else if (block.type === 'video') {
@ -211,6 +215,7 @@ export const api = {
'position': ++index, 'position': ++index,
'title': block.data.title, 'title': block.data.title,
'url': block.data.video_url, 'url': block.data.video_url,
'uuid': block.uuid,
} }
} }
} }
@ -289,8 +294,8 @@ export const api = {
'data': { 'data': {
'id': contentItem.id ? contentItem.id : null, 'id': contentItem.id ? contentItem.id : null,
'title': contentItem.title, 'title': contentItem.title,
'image_id': contentItem.img.id, 'image_id': (contentItem.img) ? contentItem.img.id:null,
'image_url': contentItem.img.image, 'image_url': (contentItem.img) ? contentItem.img.image:null,
} }
} }
} else if (contentItem.type === 'image-text') { } else if (contentItem.type === 'image-text') {
@ -300,8 +305,8 @@ export const api = {
'data': { 'data': {
'id': contentItem.id ? contentItem.id : null, 'id': contentItem.id ? contentItem.id : null,
'title': contentItem.title, 'title': contentItem.title,
'image_id': contentItem.img.id, 'image_id': (contentItem.img) ? contentItem.img.id:null,
'image_url': contentItem.img.image, 'image_url': (contentItem.img) ? contentItem.img.image:null,
'text': contentItem.txt, 'text': contentItem.txt,
} }
} }

Loading…
Cancel
Save