diff --git a/project/templates/blocks/footer.html b/project/templates/blocks/footer.html index 68709a25..9dc918e0 100644 --- a/project/templates/blocks/footer.html +++ b/project/templates/blocks/footer.html @@ -9,7 +9,7 @@
@@ -304,9 +302,9 @@ status: null, category: null, categorySelect: null, - duration: 1, + duration: null, author: null, - price: 0, + price: null, url: '', coverImage: '', coverImageId: null, @@ -390,6 +388,10 @@ duration: "Продолжительность", category: "Категория", }, + lessonFields: { + title: "Название урока", + short_description: "Описание урока", + }, showErrors: false, savingTimeout: null, savingDebounceTimeout: null, @@ -435,8 +437,16 @@ required, numeric, minValue: minValue(1) - } + }, }, + currentLesson: { + title: { + required + }, + short_description: { + required + }, + } }; } }, @@ -541,12 +551,18 @@ }); }, onLessonSubmit() { + if(!this.validateLesson()) { + return; + } + + this.saveLesson(); + }, + saveLesson() { 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; const newLesson = api.convertLessonJson(response.data); newLesson.course_id = this.course.id; this.currentLesson = newLesson; @@ -556,13 +572,37 @@ if (this.lessons && Array.isArray(this.lessons)) { this.lessons.forEach((lesson, index) => { if (newLesson.id === lesson.id) { - this.$set('lessons', index, newLesson); + this.$set(this.lessons, index, newLesson); } }); } + + document.getElementById('course-redactor__saving-status').innerText = 'СОХРАНЕНО'; + this.savingTimeout = setTimeout(() => { + document.getElementById('course-redactor__saving-status').innerText = ''; + }, 2000); + + showNotification("success", 'Урок сохранён'); + this.goToLessons(); + + this.lessonSaving = false; }) .catch((err) => { this.lessonSaving = 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()); + console.log(err); + if(err.response) { + for(let i in err.response.data) { + if(typeof err.response.data[i] === "array") { + showNotification("error", this.lessonFields[i]+": "+err.response.data[i].join(', ')); + } + } + } }); }, goToLessons() { @@ -652,15 +692,32 @@ } }, validate(silent) { - //console.log('valadte', arguments); + console.log('validate', this.$v.$invalid); + this.showErrors = true; + if (this.$v.course.$invalid) { + if(!silent) { + for(let i in this.$v.course) { + if(this.$v.course[i].$invalid) { + showNotification("error", "Ошибка валидации поля "+this.fields[i]); + } + } + } + // showNotification("error", "Заполните все необходимые поля"); + return false; + } + + return true; + }, + validateLesson(silent) { + console.log('validate', this.$v.$invalid); this.showErrors = true; - if (this.$v.$invalid) { + if (this.$v.currentLesson.$invalid) { if(!silent) { - for(let i in this.$v.course) { - if(this.$v.course[i].$invalid) { - showNotification("error", "Ошибка валидации поля "+this.fields[i]); - } - } + for(let i in this.$v.currentLesson) { + if(this.$v.currentLesson[i].$invalid) { + showNotification("error", "Ошибка валидации поля "+this.lessonFields[i]); + } + } } // showNotification("error", "Заполните все необходимые поля"); return false; @@ -671,13 +728,18 @@ onCoursePreview() { if(this.course.id) { let url; - if(this.live) { - url = `/school/lessons/${this.course.id}`; + + if(this.currentLesson && this.currentLesson.id) { + url = `/lesson/${this.currentLesson.id}`; } else { - if (this.course.url) { - url = `/course/${this.course.url}`; + if(this.live) { + url = `/school/lessons/${this.course.id}`; + } else { + if (this.course.url) { + url = `/course/${this.course.url}`; + } + url = `/course/${this.course.id}`; } - url = `/course/${this.course.id}`; } let newTab = window.open(url, '_blank'); @@ -781,12 +843,12 @@ }, 2000); // alert('Произошло что-то страшное: '+err.toString()); //console.log(err.response.data); - if(err.response.data) { + if(err.response) { for(let i in err.response.data) { - showNotification("error", this.fields[i]+": "+err.response.data[i].join(', ')); + if(typeof err.response.data[i] === "array") { + showNotification("error", this.fields[i] + ": " + err.response.data[i].join(', ')); + } } - } else { - showNotification("error", "Ошибка "+err.toString()); } }); }, 500); @@ -883,28 +945,28 @@ }); } - let user = api.getCurrentUser(this.accessToken); - promises.push(user); - - user.then((response) => { - if (response.data) { - this.me = response.data; - - if(this.me.role == ROLE_ADMIN) { - api.getUsers({role: [ROLE_AUTHOR,ROLE_ADMIN], page_size: 1000}, this.accessToken) - .then((usersResponse) => { - if (usersResponse.data) { - this.users = usersResponse.data.results.map((user) => { - return { - title: `${user.first_name} ${user.last_name}`, - value: user.id - } - }); - } - }); - } - } - }); + // let user = api.getCurrentUser(this.accessToken); + // promises.push(user); + // + // user.then((response) => { + // if (response.data) { + // this.me = response.data; + // + // if(this.me.role == ROLE_ADMIN) { + // api.getUsers({role: [ROLE_AUTHOR,ROLE_ADMIN], page_size: 1000}, this.accessToken) + // .then((usersResponse) => { + // if (usersResponse.data) { + // this.users = usersResponse.data.results.map((user) => { + // return { + // title: `${user.first_name} ${user.last_name}`, + // value: user.id + // } + // }); + // } + // }); + // } + // } + // }); // if (this.courseId) { // this.loadCourse().then(()=>{this.updateViewSection(window.location, 'load')}).catch(()=>{ @@ -967,23 +1029,23 @@ this.course.category = value.value; } }, - userSelect: { - get() { - if (!this.users || this.users.length === 0 || !this.course || !this.course.author) { - return null; - } - let value; - this.users.forEach((user) => { - if (user.value === this.course.author) { - value = user; - } - }); - return value; - }, - set(value) { - this.course.author = value.value; - } - }, + // userSelect: { + // get() { + // if (!this.users || this.users.length === 0 || !this.course || !this.course.author) { + // return null; + // } + // let value; + // this.users.forEach((user) => { + // if (user.value === this.course.author) { + // value = user; + // } + // }); + // return value; + // }, + // set(value) { + // this.course.author = value.value; + // } + // }, courseFullUrl() { if (!this.course.url) { return `https://lil.city/course/${this.course.id}`; @@ -1118,5 +1180,12 @@ background: white; border-radius: 10px; } + + .course-redactor__preview-button-bg-save { + background-color: #58fffb; + } + .course-redactor__preview-button { + transition: backgroundColor 0.5s ease-in-out; + } diff --git a/web/src/components/LessonRedactor.vue b/web/src/components/LessonRedactor.vue index cbc433d4..82faaadb 100644 --- a/web/src/components/LessonRedactor.vue +++ b/web/src/components/LessonRedactor.vue @@ -14,52 +14,56 @@
{{ title }}
-
+
-
+
-
- - - - +
+ - -
+ + + + +
+
@@ -78,10 +82,12 @@ import BlockImageText from './blocks/BlockImageText' import BlockVideo from './blocks/BlockVideo' import {api} from "../js/modules/api"; + import Draggable from 'vuedraggable'; + import _ from 'lodash' export default { name: "lesson-redactor", - props: ["lesson", "saving", "accessToken"], + props: ["lesson", "saving", "accessToken", "$v"], methods: { goBack() { this.$emit('back'); @@ -113,6 +119,7 @@ 'block-image-text': BlockImageText, 'block-images': BlockImages, 'block-video': BlockVideo, + 'vue-draggable': Draggable, } } diff --git a/web/src/js/modules/api.js b/web/src/js/modules/api.js index 112ea9b7..59c98939 100644 --- a/web/src/js/modules/api.js +++ b/web/src/js/modules/api.js @@ -1,19 +1,51 @@ import axios from 'axios'; import moment from 'moment'; +import {showNotification} from "../../js/modules/notification"; axios.defaults.headers.post['Content-Type'] = 'application/json'; axios.defaults.headers.post['Accept'] = 'application/json'; export const api = { + get: (url, params) => { + let request = axios.get(url, params); + request.catch(api.errorHandler); + return request; + }, + post: (url, data, params) => { + let request = axios.post(url, data, params); + request.catch(api.errorHandler); + return request; + }, + put: (url, data, params) => { + let request = axios.put(url, data, params); + request.catch(api.errorHandler); + return request; + }, + patch: (url, data, params) => { + let request = axios.patch(url, data, params); + request.catch(api.errorHandler); + return request; + }, + delete: (url, params) => { + let request = axios.delete(url, params); + request.catch(api.errorHandler); + return request; + }, + errorHandler: (error) => { + console.log('всё очень плохо', error, error.response); + if(error.response.status >= 500) { + showNotification("error", "Ошибка сервера "+error.toString()); + } + }, getCurrentUser: (accessToken) => { - return axios.get('/api/v1/users/me/', { + return api.get('/api/v1/users/me/', { headers: { 'Authorization': `Token ${accessToken}`, } }); }, getUsers: (params, accessToken) => { - return axios.get('/api/v1/users/', { + return api.get('/api/v1/users/', { params: params, headers: { 'Authorization': `Token ${accessToken}`, @@ -21,14 +53,14 @@ export const api = { }); }, getCategories: (accessToken) => { - return axios.get('/api/v1/categories/', { + return api.get('/api/v1/categories/', { headers: { 'Authorization': `Token ${accessToken}`, } }); }, uploadImage: (imageData, accessToken) => { - return axios.post('/api/v1/image-objects/', { + return api.post('/api/v1/image-objects/', { image: imageData, }, { headers: { @@ -37,21 +69,21 @@ export const api = { }); }, removeImage: (imageId, accessToken) => { - return axios.delete(`/api/v1/image-objects/${imageId}/`, { + return api.delete(`/api/v1/image-objects/${imageId}/`, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, loadCourse: (courseId, accessToken) => { - return axios.get(`/api/v1/courses/${courseId}/`, { + return api.get(`/api/v1/courses/${courseId}/`, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, loadLive: (courseId, accessToken) => { - return axios.get(`/api/v1/live-lesson/${courseId}/`, { + return api.get(`/api/v1/live-lesson/${courseId}/`, { headers: { 'Authorization': `Token ${accessToken}`, } @@ -360,56 +392,56 @@ export const api = { }); }, addCourse: (courseJson, accessToken) => { - return axios.post('/api/v1/courses/', courseJson, { + return api.post('/api/v1/courses/', courseJson, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, updateCourse: (courseId, courseJson, accessToken) => { - return axios.put(`/api/v1/courses/${courseId}/`, courseJson, { + return api.put(`/api/v1/courses/${courseId}/`, courseJson, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, addLive: (courseJson, accessToken) => { - return axios.post('/api/v1/live-lesson/', courseJson, { + return api.post('/api/v1/live-lesson/', courseJson, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, updateLive: (courseId, courseJson, accessToken) => { - return axios.put(`/api/v1/live-lesson/${courseId}/`, courseJson, { + return api.put(`/api/v1/live-lesson/${courseId}/`, courseJson, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, getCourseLessons: (courseId, accessToken) => { - return axios.get(`/api/v1/lessons/?course=${courseId}`, { + return api.get(`/api/v1/lessons/?course=${courseId}`, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, removeCourseLesson: (lessonId, accessToken) => { - return axios.delete(`/api/v1/lessons/${lessonId}/`, { + return api.delete(`/api/v1/lessons/${lessonId}/`, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, addLesson: (lessonJson, accessToken) => { - return axios.post('/api/v1/lessons/', lessonJson, { + return api.post('/api/v1/lessons/', lessonJson, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, updateLesson: (lessonId, lessonJson, accessToken) => { - return axios.put(`/api/v1/lessons/${lessonId}/`, lessonJson, { + return api.put(`/api/v1/lessons/${lessonId}/`, lessonJson, { headers: { 'Authorization': `Token ${accessToken}`, } @@ -437,28 +469,28 @@ export const api = { if (!removeUrl) { return; } - return axios.delete(removeUrl, { + return api.delete(removeUrl, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, getCourseDraft: (accessToken) => { - return axios.get('/api/v1/courses/draft/', { + return api.get('/api/v1/courses/draft/', { headers: { 'Authorization': `Token ${accessToken}`, } }); }, publishCourse: (courseId, accessToken) => { - return axios.patch(`/api/v1/courses/${courseId}/`, {status: 1}, { + return api.patch(`/api/v1/courses/${courseId}/`, {status: 1}, { headers: { 'Authorization': `Token ${accessToken}`, } }); }, getSchedule: (accessToken, params) => { - return axios.get('/api/v1/school-schedules/', { + return api.get('/api/v1/school-schedules/', { params: params, headers: { 'Authorization': `Token ${accessToken}`,