You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1043 lines
46 KiB

<template>
<div id="lilcity__course-redactor" v-on:course_publish="onCoursePublish" v-on:course_preview="onCoursePreview">
<div v-if="!courseLoading && !mounting">
<form v-if="viewSection !== 'lessons-edit'" @submit.prevent="onSubmit">
<div class="info">
<div class="info__section">
<div class="courses__item">
<div class="courses__preview">
<img class="courses__pic" name="course-cover" :src="course.coverImage || defaultCover" width="300px" />
<div class="upload" v-if="! course.coverImage">
<div class="upload__title">Загрузить превью</div>
<input type="file" class="upload__file" name="course-cover-upload" @change="onCoverImageSelected">
</div>
<a href="#" title="Удалить превью" class="course-delete-cover" v-if="course.coverImage" @click="removeCover"
name="course-cover-delete">
<svg class="icon icon-delete">
<use xlink:href="/static/img/sprite.svg#icon-delete"></use>
</svg>
</a>
</div>
<div class="courses__details">
<div class="field-category courses__theme theme field info__field--light" v-if="!live" v-bind:class="{ error: (!$v.live && $v.course.category.$dirty || showErrors) && $v.course.category.$invalid }">
<lil-select :value.sync="course.category" :options="categoryOptions"
placeholder="Выберите категорию" name="course-category"/>
</div>
<div class="courses__old-price" v-if="course.is_paid && course.old_price"><s>{{ course.old_price }}₽</s></div>
<div class="courses__price" v-if="course.is_paid && course.price">{{ course.price }}₽</div>
</div>
<div class="courses__title field field" v-bind:class="{ error: ($v.course.title.$dirty || showErrors) && $v.course.title.$invalid }">
<textarea class="field__textarea" name="course-title"
rows="1"
:title="titles.courseTitle"
v-autosize="course.title"
@change="onCourseNameInput"
v-model="course.title"
placeholder="Добавить заголовок"></textarea>
</div>
<div class="courses__content field" style="width: 300px;" name="course-short-description"
v-bind:class="{ error: ($v.course.short_description.$dirty || showErrors) && $v.course.short_description.$invalid }">
<vue-redactor :value.sync="course.short_description" placeholder="Добавить краткое описание"/>
</div>
</div>
</div>
<div class="info__sidebar">
<div class="info__wrap">
<div class="info__fieldset" style="margin-bottom: 20px;">
<div v-if="!live" class="info__field field">
<div class="field__label field__label_gray">ССЫЛКА</div>
<div class="field__wrap">
<input type="text" class="field__input" name="course-slug" v-model="course.slug" @input="slugChanged = true">
</div>
<div class="field__wrap field__wrap--additional">{{ courseFullUrl }}</div>
</div>
<div v-if="live" class="info__field field"
v-bind:class="{ error: ($v.course.stream.$dirty || showErrors) && $v.course.stream.$invalid }">
<div class="field__label field__label_gray">ССЫЛКА НА VIMEO</div>
<div class="field__wrap">
<input type="text" name="course-stream" class="field__input" v-model="course.stream">
</div>
</div>
<!-- <div v-if="live" class="info__field field"
v-bind:class="{ error: ($v.course.date.$dirty || showErrors) && $v.course.date.$invalid }">
<div class="field__label">ДАТА</div>
<div class="field__wrap">
<lil-select :value.sync="course.date" :options="scheduleOptions" placeholder="Выберите дату"/>
</div>
</div> -->
<div v-if="!live" class="info__field field">
<div class="field__label field__label_gray">ДОСТУП</div>
<div class="field__wrap">
<label class="field__switch switch switch_lg switch_circle">
<input type="radio" :value="false" class="switch__input" v-model="course.is_paid"
name="course-is-paid-input">
<span class="switch__content" name="course-is-paid-no">Бесплатный</span>
</label>
<label class="field__switch switch switch_lg switch_circle">
<input type="radio" :value="true" class="switch__input" v-model="course.is_paid"
name="course-is-paid-input">
<span class="switch__content" name="course-is-paid-yes">Платный</span>
</label>
</div>
</div>
<div class="info__field field field_info" v-if="!live && course.is_paid"
v-bind:class="{ error: ($v.course.access_duration.$dirty || showErrors)
&& $v.course.access_duration.$invalid }">
<div class="field__label field__label_gray">ПРОДОЛЖИТЕЛЬНОСТЬ ДОСТУПА</div>
<div class="field__wrap field__wrap__appended">
<input type="text" class="field__input field__input__appended" v-model.number="course.access_duration"
@input="$v.course.access_duration.$touch()" name="course-access-duration">
<button disabled class="field__append">{{pluralize(course.access_duration, ['день', 'дня', 'дней'])}}</button>
</div>
</div>
<div style="display: flex;">
<div v-if="course.is_paid" class="info__field field">
<div class="field__label field__label_gray">СТОИМОСТЬ</div>
<div class="field__wrap field__wrap__appended" style="width: 120px;">
<input type="text" class="field__input field__input__appended" v-model.number.lazy="displayPrice"
name="course-price">
<button disabled class="field__append">руб.</button>
</div>
</div>
<div v-if="course.is_paid" class="info__field field" style="margin-left: 10px;">
<div class="field__label field__label_gray">СТОИМОСТЬ БЕЗ СКИДКИ</div>
<div class="field__wrap field__wrap__appended">
<input type="text" class="field__input field__input__appended" v-model.number.lazy="displayOldPrice"
name="course-old-price">
<button disabled class="field__append">руб.</button>
</div>
</div>
</div>
<div v-if="!live" class="info__field field">
<div class="field__label field__label_gray">ВОЗРАСТ</div>
<div class="field__wrap">
<lil-select :value.sync="course.age" :options="ages" value-key="value" name="course-age"
placeholder="Выберите возраст"/>
</div>
</div>
<label v-if="me && !live && me.role === ROLE_ADMIN" class="info__switch switch switch_lg">
<input type="checkbox" class="switch__input" v-model="course.is_featured">
<span class="switch__content" name="course-is-featured">Выделить</span>
</label>
</div>
<div v-if="!live" class="info__fieldset">
<div class="info__field field">
<div class="field__label field__label_gray">ЗАПУСК</div>
<div class="field__wrap">
<label class="field__switch switch switch_lg switch_circle">
<input type="radio" :value="false" class="switch__input" v-model="course.is_deferred"
name="course-is-deferred-input">
<span class="switch__content" name="course-is-deferred-no">Мгновенный</span>
</label>
<label class="field__switch switch switch_lg switch_circle">
<input type="radio" :value="true" class="switch__input" v-model="course.is_deferred"
name="course-is-deferred-input">
<span class="switch__content" name="course-is-deferred-yes">Отложенный</span>
</label>
</div>
</div>
<div class="datetime-fields" v-show="course.is_deferred">
<div class="info__field field">
<div class="field__label">ДАТА</div>
<div class="field__wrap">
<vue-datepicker :disabled="disabledDates" input-class="field__input" name="course-date"
v-model="course.date" language="ru" format="dd/MM/yyyy"/>
</div>
</div>
<div class="field-time info__field field">
<div class="field__label">ВРЕМЯ</div>
<div class="field__wrap">
<lil-select :value.sync="course.time" value-key="value" :options="timeOptions" name="course-time"
placeholder="Выберите время"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="section">
<div class="section__center center">
<div class="kit" style="margin: 0 auto;">
<div v-if="!live" id="course-redactor__nav" class="kit__nav">
<button class="kit__btn btn btn_lg" name="course-content-btn"
v-bind:class="{ 'btn_stroke': viewSection === 'course', 'btn_gray': viewSection !== 'course' }"
type="button" @click="showCourse">Описание
курса
</button>
<button class="kit__btn btn btn_lg" name="course-lessons-btn"
v-bind:class="{ 'btn_stroke': viewSection === 'lessons', 'btn_gray': viewSection !== 'lessons' }"
type="button"
@click="showLessons"
:disabled="!course.id">
Уроки
</button>
</div>
<div v-if="viewSection === 'course'" class="kit__body">
<block-content :content.sync="course.content" name="course-content"></block-content>
<!--<div class="kit__foot">
<button type="submit" class="kit__submit btn btn_md" v-bind:class="{ loading: courseSaving }">
Сохранить
</button>
</div>-->
</div>
<div v-if="viewSection === 'lessons'" class="kit__body">
<div class="lessons__title title">Содержание курса</div>
<div v-if="!lessonsLoading" class="lessons__list">
<vue-draggable v-model="lessons" @start="drag=true" @end="onLessonsChanged" name="course-lessons"
:options="{ handle: '.sortable__handle' }">
<div class="lessons__item" v-for="(lesson, index) in lessons" :key="lesson.id">
<div class="lessons__actions">
<button class="sortable__handle" type="button">
<svg class="icon icon-hamburger">
<use xlink:href="/static/img/sprite.svg#icon-hamburger"></use>
</svg>
</button>
<button type="button" class="lessons__action" @click="removeLesson(index)">
<svg class="icon icon-delete">
<use xlink:href="/static/img/sprite.svg#icon-delete"></use>
</svg>
</button>
<button type="button" class="lessons__action" @click="editLesson(index)">
<svg class="icon icon-edit">
<use xlink:href="/static/img/sprite.svg#icon-edit"></use>
</svg>
</button>
</div>
<div class="lessons__subtitle subtitle">{{ lesson.title }}</div>
<div class="lessons__row">
<div class="lessons__content" v-html="lesson.short_description"></div>
</div>
</div>
</vue-draggable>
</div>
<div v-if="lessonsLoading">Загрузка...</div>
<div class="lessons__foot">
<button type="button" class="lessons__btn btn btn_md" @click="addLesson"
name="course-add-lesson">СОЗДАТЬ УРОК</button>
</div>
</div>
</div>
</div>
</div>
</form>
<form v-if="viewSection === 'lessons-edit'" @submit.prevent="onLessonSubmit">
<lesson-redactor :$v="$v" :lesson.sync="currentLesson" :saving.sync="lessonSaving" :access-token="accessToken"
v-on:back="goToLessons" name="course-lesson-edit" />
</form>
</div>
<div v-else>
<div class="section">
<div class="section__center center">
<h1>Загрузка...</h1>
</div>
</div>
</div>
</div>
</template>
<script>
import { ROLE_ADMIN, ROLE_AUTHOR } from './consts'
import LinkInput from './inputs/LinkInput'
import DatePicker from 'vuejs-datepicker'
import BlockContent from './blocks/BlockContent'
import VueRedactor from './redactor/VueRedactor';
import LilSelect from "./inputs/LilSelect";
import LessonRedactor from "./LessonRedactor";
import {api} from "../js/modules/api";
import $ from 'jquery';
import {required, minValue, numeric, url } from 'vuelidate/lib/validators'
import slugify from 'slugify';
import Draggable from 'vuedraggable';
import {showNotification} from "../js/modules/notification";
import createHistory from "history/createBrowserHistory";
import moment from 'moment'
import _ from 'lodash'
const history = createHistory();
export default {
name: "course-redactor",
props: ["authorName", "authorPicture", "accessToken", "courseId", "live"],
data() {
return {
disabledDates: {
to: new Date(new Date().setDate(new Date().getDate() - 1)),
},
titles: {},
mounting: false,
viewSection: 'course',
me: null,
users: null,
ROLE_ADMIN: ROLE_ADMIN,
slugChanged: false,
defaultCover: '/img/no_cover.png',
course: {
title: '',
status: null,
category: null,
categorySelect: null,
access_duration: null,
author: null,
price: null,
old_price: null,
age: 0,
slug: '',
url: '',
coverImage: '',
kit__body: null,
is_paid: false,
is_featured: true,
is_deferred: false,
date: '',
stream: '',
time: null,
short_description: '',
content: [],
gallery: {
images: [],
}
},
courseLoading: false,
courseSaving: false,
lessons: [],
lessonsLoading: false,
lessonSaving: false,
currentLesson: {
title: '',
short_description: '',
content: [],
},
is_adding_block: false,
timeOptions: [
{
'title': '10:00',
'value': '10:00',
},
{
'title': '11:00',
'value': '11:00',
},
{
'title': '12:00',
'value': '12:00',
},
{
'title': '13:00',
'value': '13:00',
},
{
'title': '14:00',
'value': '14:00',
},
{
'title': '15:00',
'value': '15:00',
},
{
'title': '16:00',
'value': '16:00',
},
{
'title': '17:00',
'value': '17:00',
},
{
'title': '18:00',
'value': '18:00',
}
],
ages: [
{
'title': 'Любой возраст',
'value': 0,
},
{
'title': 'до 5',
'value': 1,
},
{
'title': '5-10',
'value': 2,
},
{
'title': '10-18',
'value': 3,
},
{
'title': 'от 18',
'value': 4,
},
],
weekdays: [
'',
'Понедельник',
'Вторник',
'Среда',
'Четверг',
'Пятница',
'Суббота',
'Воскресенье',
],
fields: {
title: "Заголовок",
short_description: "Краткое описание",
stream: "Ссылка на Vimeo",
date: "Дата",
access_duration: "Продолжительность доступа",
category: "Категория",
},
lessonFields: {
title: "Название урока",
short_description: "Описание урока",
},
showErrors: false,
savingTimeout: null,
savingDebounceTimeout: null,
categoryOptions: [],
scheduleOptions: [],
courseSyncHook: false, // Если true, то watch не будет отправлять курс на обновление
}
},
validations() {
if(this.live) {
return {
course: {
title: {
required
},
short_description: {
required
},
stream: {
required,
// url
},
date: {
required
},
},
};
} else {
return {
course: {
title: {
required
},
short_description: {
required
},
access_duration: {
required: this.course.is_paid ? required : false,
numeric,
minValue: minValue(1)
},
category: {
required,
numeric,
minValue: minValue(1)
},
},
currentLesson: {
title: {
required
},
short_description: {
required
},
}
};
}
},
methods: {
removeCover() {
if(! this.course.coverImageId){
return;
}
api.removeImage(this.course.coverImageId, this.accessToken)
.then(response => {
this.course.coverImageId = null;
this.course.coverImage = null;
});
},
onCoverImageSelected(event) {
let file = event.target.files[0];
let reader = new FileReader();
reader.onload = () => {
this.$set(this.course, 'coverImage', reader.result);
api.uploadImage(reader.result, this.accessToken)
.then((response) => {
this.course.coverImageId = response.data.id;
})
.catch((error) => {
//console.log('error', error);
});
};
if (file) {
reader.readAsDataURL(file);
}
},
onCoursePriceChange(event) {
this.course.price = event.target.value;
},
getSlug(text) {
return slugify(text || '').toLowerCase().replace(/[^-\w]+$/, '').replace(/[^-\w]/g, '-');
},
onCourseNameInput() {
this.$v.course.title.$touch();
if (!this.slugChanged && !this.$v.course.status) {
this.course.slug = this.getSlug(this.course.title);
}
},
removeLesson(lessonIndex) {
if (!confirm('Вы действительно хотите удалить этот урок?')) {
return;
}
const lesson = this.lessons[lessonIndex];
if (lesson.hasOwnProperty('id') && lesson.id) {
api.removeCourseLesson(lesson.id, this.accessToken);
}
this.lessons.splice(lessonIndex, 1);
this.onLessonsChanged();
},
editLesson(lessonIndex) {
this.currentLesson = this.lessons[lessonIndex];
history.push(`/course/${this.course.id}/lessons/${this.currentLesson.id}/edit`);
this.viewSection = 'lessons-edit';
},
showCourse() {
if (this.viewSection !== 'course') {
history.push(this.course.id ? `/course/${this.course.id}/edit` : "/course/create");
}
this.viewSection = 'course'
},
showLessons() {
if (this.viewSection !== 'lessons') {
history.push(`/course/${this.course.id}/edit/lessons`);
}
this.viewSection = 'lessons';
},
addLesson() {
this.currentLesson = {
title: '',
short_description: '',
content: [],
};
if (this.viewSection !== 'lessons-edit') {
history.push(`/course/${this.course.id}/lessons/new`);
}
this.viewSection = 'lessons-edit';
window.scrollTo(0, 0);
},
onSubmit() {
//console.log('onSubmit');
this.courseSaving = true;
api.saveCourse(this.course, this.accessToken)
.then((response) => {
this.courseSaving = false;
this.processCourseJson(response.data);
})
.catch((err) => {
this.courseSaving = false;
});
},
onLessonSubmit() {
if(!this.validateLesson()) {
return new Promise(function(resolve, reject) {
reject('validation reject');
});
}
showNotification("success", "Момент, вносим последние правки!");
return this.saveLesson();
},
saveLesson() {
this.lessonSaving = true;
const currentLessonId = this.currentLesson.id;
this.currentLesson.course_id = this.course.id;
let req = api.saveLesson(this.currentLesson, this.accessToken);
req.then((response) => {
const newLesson = api.convertLessonJson(response.data);
newLesson.course_id = this.course.id;
this.currentLesson = newLesson;
if (!currentLessonId) {
this.lessons.push(newLesson);
}
if (this.lessons && Array.isArray(this.lessons)) {
this.lessons.forEach((lesson, index) => {
if (newLesson.id === lesson.id) {
this.$set(this.lessons, index, newLesson);
}
});
}
this.changeSavingStatus(true);
showNotification("success", 'Урок сохранён');
// this.goToLessons();
this.lessonSaving = false;
})
.catch((err) => {
this.lessonSaving = false;
//console.error(err);
this.changeSavingStatus(true, true);
// 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(', '));
}
}
}
});
return req;
},
goToLessons() {
history.push(`/course/${this.course.id}/edit/lessons`);
this.viewSection = 'lessons';
this.$nextTick(() => {
const elementTop = $('#course-redactor__nav').position().top - 130;
$(window).scrollTop(elementTop);
});
},
processCourseJson(data) {
this.course = api.convertCourseJson(data);
this.course.live = this.live;
this.lessons = data.lessons.map((lessonJson) => {
return api.convertLessonJson(lessonJson);
});
},
loadCourseDraft() {
//console.log('loadCourseDraft');
if(this.live) { return; }
this.courseLoading = true;
let response = api.getCourseDraft(this.accessToken);
response
.then((response) => {
this.processCourseJson(response.data);
this.courseLoading = false;
})
.catch((err) => {
this.courseLoading = false;
//console.log('error course loading', err);
});
return response;
},
loadCourse() {
//console.log('loadCourse');
this.courseLoading = true;
let request = null;
if(this.live) {
request = api.loadLive(this.courseId, this.accessToken)
} else {
request = api.loadCourse(this.courseId, this.accessToken)
}
request
.then((response) => {
this.processCourseJson(response.data);
this.$nextTick(() => {
this.courseLoading = false;
});
this.lessons.sort((a, b) => {
if (a.position > b.position) {
return 1;
}
if (a.position < b.position) {
return -1;
}
return 0;
});
})
.catch((err) => {
this.courseLoading = false;
//console.log('error course loading', err);
});
return request;
},
loadLessons(courseId) {
},
onCoursePublish() {
if(this.validate()) {
const publishButton = $('#course-redactor__publish-button');
publishButton.attr('disabled', 'disabled');
if(this.live) {
window.location = '/school/lessons';
} else {
api.publishCourse(this.course, this.accessToken)
.then((response) => {
window.location = '/course/on-moderation';
})
.catch(() => {
publishButton.removeAttr('disabled');
});
}
}
},
validate(silent) {
console.log('validate', this.$v.$invalid);
if(!silent) {
this.showErrors = true;
if (this.$v.course.$invalid) {
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.currentLesson.$invalid) {
if(!silent) {
for(let i in this.$v.currentLesson) {
if(this.$v.currentLesson[i].$invalid) {
showNotification("error", "Ошибка валидации поля "+this.lessonFields[i]);
}
}
}
// showNotification("error", "Заполните все необходимые поля");
return false;
}
return true;
},
onCoursePreview() {
if(this.course.id) {
let url;
if(this.viewSection === 'lessons-edit') {
this.onLessonSubmit().then(()=>{
url = `/lesson/${this.currentLesson.id}`;
let newTab = window.open(url, '_blank');
newTab.focus();
}).catch((e)=>{
// showNotification("error", "Пока еще нечего посмотреть, давайте что-нибудь напишем");
console.log(e);
});
} else {
if(this.live) {
url = `/school/lessons/${this.course.id}`;
} else {
if (this.course.url) {
url = `/course/${this.course.url}`;
}
url = `/course/${this.course.id}`;
}
let newTab = window.open(url, '_blank');
newTab.focus();
}
} else {
showNotification("error", "Пока еще нечего посмотреть, давайте что-нибудь напишем");
}
},
saveCourseDraft: function (newValue, oldValue) {
if (this.savingDebounceTimeout) {
clearTimeout(this.savingDebounceTimeout);
}
this.courseSyncHook = false;
this.savingDebounceTimeout = setTimeout(() => {
if(!this.validate(true)) {
return;
}
this.courseSaving = true;
this.changeSavingStatus();
const courseObject = this.course;
courseObject.slug = this.getSlug(courseObject.slug);
api.saveCourse(courseObject, this.accessToken)
.then((response) => {
this.courseSaving = false;
this.changeSavingStatus(true);
this.courseSyncHook = true;
const courseData = api.convertCourseJson(response.data);
this.course.slug = courseData.slug;
if (this.course.coverImage) {
courseData.coverImage = this.course.coverImage;
}
if (this.course.is_deferred) {
courseData.is_deferred = true;
}
let remoteUUIDMapper = {}
let remoteDataMapper = {}
if (courseData.content) {
courseData.content.forEach((contentElement) => {
remoteUUIDMapper[contentElement.uuid] = contentElement.data.id;
remoteDataMapper[contentElement.uuid] = contentElement.data;
})
}
this.course.content.forEach((contentElement, index) => {
if (!contentElement.data.id) {
this.$set(this.course.content[index].data, 'id', remoteUUIDMapper[contentElement.uuid])
}
if(contentElement.type === 'images') {
remoteDataMapper[contentElement.uuid].images.forEach((image, imageIndex) => {
this.$set(this.course.content[index].data.images[imageIndex], 'id', image.id)
})
}
});
if(courseData.id) {
this.course.id = courseData.id;
}
this.$nextTick(() => {
this.courseSyncHook = false;
});
})
.catch((err) => {
this.courseSyncHook = false;
this.courseSaving = false;
this.changeSavingStatus(true, true);
if(err.response) {
for(let i in err.response.data) {
if(typeof err.response.data[i] === "array") {
showNotification("error", this.fields[i] + ": " + err.response.data[i].join(', '));
}
}
}
});
}, 500);
},
updateViewSection(location, action) {
//console.log('updateViewSection[action]', action);
if (location.pathname.match(/course\/\d+\/edit\/lessons/)) {
this.viewSection = 'lessons';
} else if (location.pathname.match(/course\/\d+\/lessons\/new/)){
this.viewSection = 'lessons-edit';
} else if (location.pathname.match(/course\/\d+\/lessons\/\d+\/edit/)) {
// let lessonId = parseInt(location.pathname.split('/').pop());
const lessonId = +location.pathname.match(/lessons\/(\d+)\/edit/)[1];
this.currentLesson = this.lessons.find((i)=>{return i.id === lessonId});
this.viewSection = 'lessons-edit';
} else {
this.viewSection = 'course';
}
},
onLessonsChanged() {
let promises = [];
this.courseSaving = true;
this.lessons.map((lesson, index) => {
lesson.position = index + 1;
lesson.course_id = this.course.id;
let res = api.saveLesson(lesson, this.accessToken);
promises.push(res);
});
Promise.all(promises).then(() => {
this.courseSaving = false;
this.changeSavingStatus(true);
}, () => {
this.courseSaving = false;
this.changeSavingStatus(true, true);
});
},
pluralize(count, words) {
var cases = [2, 0, 1, 1, 1, 2];
return words[ (count % 100 > 4 && count % 100 < 20) ? 2 : cases[ Math.min(count % 10, 5)] ];
},
changeSavingStatus(saved, error) {
let text = '';
if(error) {
text = 'ОШИБКА';
} else {
text = saved ? 'СОХРАНЕНО' : 'СОХРАНЕНИЕ...';
}
clearTimeout(this.savingTimeout);
document.getElementById('course-redactor__saving-status').innerText = text;
if(saved || error){
this.savingTimeout = setTimeout(() => {
document.getElementById('course-redactor__saving-status').innerText = '';
}, 2000);
}
},
},
mounted() {
this.mounting = true;
moment.locale('ru');
this.titles['courseTitle'] = 'НАЗВАНИЕ КУРСА';
this.titles['shortDescription'] = 'КРАТКО О КУРСЕ';
if(this.live) {
this.titles['courseTitle'] = 'НАЗВАНИЕ УРОКА';
this.titles['shortDescription'] = 'КРАТКО ОБ УРОКЕ';
}
this.course.live = this.live;
// Listen for changes to the current location.
this.unlisten = history.listen(this.updateViewSection);
let promises = [];
let cats = api.getCategories(this.accessToken);
promises.push(cats);
cats.then((response) => {
if (response.data) {
this.categoryOptions = response.data;
}
});
if(this.live) {
let schedule = api.getSchedule(this.accessToken, {live_lesson_exist: false});
promises.push(schedule);
schedule.then((response) => {
if (response.data) {
let schedule = [];
response.data.results.forEach((item) => {
schedule[item.weekday] = item.title;
});
console.log('schedule', schedule);
let options = [];
for(let i=-7;i<=10;i++) {
let now = new Date();
now.setDate(now.getDate() + i);
let weekday = now.getDay() || 7;
console.log('data', i, now.getDay(), weekday, now, moment(now).format("D MMM"));
if(schedule[weekday]) {
options.push({
title: `${schedule[weekday]} (${this.weekdays[weekday]}, ${moment(now).format("D MMM")})`,
value: moment(now).format('YYYY-MM-DD')
});
}
}
console.log('options',options);
this.scheduleOptions = _.orderBy(options, (item)=>{return moment(item.value)});
}
});
}
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.getUser(this.me.id, {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
}
});
}
});
} */
}
});
Promise.all(promises.map(p => p.catch(e => e))).then(()=>{
this.mounting = false;
let load;
if (this.courseId) {
load = this.loadCourse()
} else {
load = this.loadCourseDraft();
}
load.then(()=>{
this.updateViewSection(window.location, 'load '+this.courseId)
})
.catch(()=>{
this.updateViewSection(window.location, 'load err '+this.courseId)
})
});
},
computed: {
displayPrice: {
get: function () {
return this.course.is_paid ? (this.course.price || '') : '';
},
set: function (value) {
this.course.price = value || 0;
}
},
displayOldPrice: {
get: function () {
return this.course.is_paid && this.course.old_price ? (this.course.old_price || '') : '';
},
set: function (value) {
this.course.old_price = value || 0;
}
},
courseFullUrl() {
let suffix = this.course.slug || this.course.id || 'ваша_ссылка';
return `https://lil.school/course/${suffix}`;
},
},
beforeDestroy() {
this.unlisten();
},
watch: {
'course': {
handler: function (newValue, oldValue) {
// Если курс загрузился и есть ID - делаем кнопки превью и публикации активными
if (newValue.id) {
$('#course-redactor__preview-button').removeAttr('disabled');
$('#course-redactor__publish-button').removeAttr('disabled');
}
if (this.courseSyncHook || this.courseLoading) {
return;
}
this.saveCourseDraft(newValue, oldValue);
},
deep: true,
},
},
components: {
LessonRedactor,
LilSelect,
BlockContent,
'link-input': LinkInput,
'vue-datepicker': DatePicker,
'lesson-redactor': LessonRedactor,
'vue-draggable': Draggable,
'vue-redactor': VueRedactor,
}
}
</script>