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.title = cdata['title']
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.save()
else:
@ -45,16 +52,29 @@ class DispatchContentMixin(object):
position=cdata['position'],
title=cdata['title'],
course=course,
img=ImageObject.objects.get(id=cdata['img']),
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':
if 'id' in cdata and cdata['id']:
it = ImageText.objects.get(id=cdata['id'])
it.position = cdata['position']
it.title = cdata['title']
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.uuid = cdata['uuid']
it.save()
@ -63,10 +83,15 @@ class DispatchContentMixin(object):
position=cdata['position'],
title=cdata['title'],
course=course,
img=ImageObject.objects.get(id=cdata['img']),
txt=cdata['txt'],
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':
if 'id' in cdata and 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(
ImageObject, related_name='content_images',
verbose_name='Объект изображения', on_delete=models.CASCADE,
null=True
)
@ -63,6 +64,7 @@ class ImageText(Content):
img = models.ForeignKey(
ImageObject, related_name='content_imagetexts',
verbose_name='Объект изображения', on_delete=models.CASCADE,
null=True
)
txt = models.TextField('Текст', default='')

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

@ -155,7 +155,7 @@ class CourseOnModerationView(TemplateView):
class CourseEditView(TemplateView):
template_name = 'course/course_edit.html'
def get(self, request, pk=None):
def get(self, request, pk=None, lesson=None):
drafts = Course.objects.filter(
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('courses/', CoursesView.as_view(), name='courses'),
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/on-moderation', CourseOnModerationView.as_view(), name='course-on-moderation'),
path('course/<int:pk>/', CourseView.as_view(), name='course'),

@ -35,6 +35,18 @@
v-model="course.title"></textarea>
</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 class="info__foot" v-if="!live">
<div class="info__field field field_info info__field--light"
@ -138,25 +150,6 @@
<div class="section">
<div class="section__center center">
<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">
<button class="kit__btn btn btn_lg"
v-bind:class="{ 'btn_stroke': viewSection === 'course', 'btn_gray': viewSection !== 'course' }"
@ -323,7 +316,11 @@
lessons: [],
lessonsLoading: false,
lessonSaving: false,
currentLesson: null,
currentLesson: {
title: '',
short_description: '',
content: [],
},
is_adding_block: false,
timeOptions: [
{
@ -469,9 +466,7 @@
},
editLesson(lessonIndex) {
this.currentLesson = this.lessons[lessonIndex];
if (this.viewSection !== 'lessons-edit') {
history.push("/course/create/lessons/new");
}
history.push("/course/create/lessons/edit/"+this.currentLesson.id);
this.viewSection = 'lessons-edit';
},
showCourse() {
@ -490,7 +485,6 @@
this.currentLesson = {
title: '',
short_description: '',
course_id: this.course.id,
content: [],
};
if (this.viewSection !== 'lessons-edit') {
@ -513,6 +507,7 @@
onLessonSubmit() {
this.lessonSaving = true;
const currentLessonId = this.currentLesson.id;
this.currentLesson.course_id = this.course.id;
api.saveLesson(this.currentLesson, this.accessToken)
.then((response) => {
this.lessonSaving = false;
@ -535,6 +530,7 @@
});
},
goToLessons() {
history.push("/course/create/lessons");
this.viewSection = 'lessons';
this.$nextTick(() => {
const elementTop = $('#course-redactor__nav').position().top - 130;
@ -543,7 +539,9 @@
},
loadCourseDraft() {
this.courseLoading = true;
api.getCourseDraft(this.accessToken)
let response = api.getCourseDraft(this.accessToken);
response
.then((response) => {
this.courseLoading = false;
this.course = api.convertCourseJson(response.data);
@ -555,10 +553,13 @@
this.courseLoading = false;
console.log('error course loading', err);
});
return response;
},
loadCourse() {
this.courseLoading = true;
api.loadCourse(this.courseId, this.accessToken)
let response = api.loadCourse(this.courseId, this.accessToken)
response
.then((response) => {
this.courseLoading = false;
this.course = api.convertCourseJson(response.data);
@ -570,6 +571,8 @@
this.courseLoading = false;
console.log('error course loading', err);
});
return response;
},
loadLessons(courseId) {
@ -651,22 +654,35 @@
.catch((err) => {
this.courseSyncHook = 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() {
console.log('live', this.live);
// Listen for changes to the current location.
this.unlisten = history.listen((location, 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';
}
});
this.unlisten = history.listen(this.updateViewSection);
api.getCategories(this.accessToken)
.then((response) => {
@ -703,10 +719,12 @@
});
if (this.courseId) {
this.loadCourse()
this.loadCourse().then(()=>{this.updateViewSection(window.location, 'load')})
} else {
this.loadCourseDraft();
this.loadCourseDraft().then(()=>{this.updateViewSection(window.location, 'load draft')});
}
// this.updateViewSection(window.location);
},
computed: {
coverBackgroundStyle() {

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

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

Loading…
Cancel
Save