remotes/origin/editis_13-01-19
gzbender 7 years ago
parent 4ccf8fe558
commit e87d5efe37
  1. 2
      apps/user/templates/user/edit-gallery.html
  2. 10
      apps/user/templates/user/profile.html
  3. 162
      web/src/components/CourseRedactor.vue
  4. 2
      web/src/components/blocks/BlockImages.vue
  5. 2
      web/src/js/app.js
  6. 29
      web/src/sass/_common.sass

@ -13,7 +13,7 @@
{% block pre_app_js %}
<script>
window.LIL_STORE._user_gallery_images = [{% for img in user.gallery.gallery_images.all %}{
window.LIL_STORE._user_gallery_images = [{% for img in user.gallery.gallery_images.reverse %}{
id: {{ img.id }},
image_thumbnail_url: '{{ img.img.image_thumbnail.url }}',
image_id: {{ img.img.id }},

@ -67,13 +67,13 @@
<div class="section__center center">
<div class="tabs js-tabs">
<div class="tabs__nav">
<button class="tabs__btn js-tabs-btn active" data-anchor="purchases">МОИ ПОКУПКИ</button>
<a href="#purchases" class="tabs__btn js-tabs-btn active">МОИ ПОКУПКИ</a>
{% if is_author %}
<button class="tabs__btn js-tabs-btn" data-anchor="courses">ОПУБЛИКОВАННЫЕ
<a href="#courses" class="tabs__btn js-tabs-btn">ОПУБЛИКОВАННЫЕ
<span class="mobile-hide">КУРСЫ</span>
</button>
</a>
{% endif %}
<button class="tabs__btn js-tabs-btn" data-anchor="works">МОИ РАБОТЫ</button>
<a href="#works" class="tabs__btn js-tabs-btn">МОИ РАБОТЫ</a>
</div>
<div class="tabs__container">
<div class="tabs__item js-tabs-item" style="display: block;">
@ -146,7 +146,7 @@
</div>
<div class="examples gallery">
{% for image in user.gallery.gallery_images.all %}
{% for image in user.gallery.gallery_images.reverse %}
<div class="examples__item">
<a href="{{ image.img.image.url }}">
{% thumbnail image.img.image "165x165" crop="center" as im %}

@ -3,63 +3,38 @@
<div v-if="!courseLoading && !mounting">
<form v-if="viewSection !== 'lessons-edit'" @submit.prevent="onSubmit">
<div class="info">
<div class="info__section" :style="coverBackgroundStyle">
<div class="info__main">
<div class="info__head">
<div class="info__user">
<div class="info__ava ava">
<img :src="authorPicture" alt="Аватар" class="ava__pic">
</div>
<div v-if="me" class="info__group info__field--light">
<div class="info__label">АВТОР</div>
<div class="info__value">{{ authorName }}</div>
</div>
</div>
<div class="info__upload upload">
Загрузить фон
<div class="info__section">
<div class="courses__item">
<div class="courses__preview">
<img class="courses__pic" :src="course.coverImage || defaultCover" width="300px" />
<div class="upload" v-if="! course.coverImage">
<div class="upload__title">Загрузить превью</div>
<input type="file" class="upload__file" @change="onCoverImageSelected">
</div>
<a href="#" title="Удалить превью" class="course-delete-cover" v-if="course.coverImage" @click="removeCover">
<svg class="icon icon-delete">
<use xlink:href="/static/img/sprite.svg#icon-delete"></use>
</svg>
</a>
</div>
<div class="info__title">
<div class="info__field field field_info"
v-bind:class="{ error: ($v.course.title.$dirty || showErrors) && $v.course.title.$invalid }">
<div class="field__label">{{titles.courseTitle}}</div>
<div class="field__wrap">
<textarea class="field__textarea"
rows="1"
:title="titles.courseTitle"
v-autosize="course.title"
@change="onCourseNameInput"
v-model="course.title"></textarea>
</div>
</div>
<div class="info__field field field_info field_short_description"
v-bind:class="{ error: ($v.course.short_description.$dirty || showErrors) && $v.course.short_description.$invalid }">
<div class="field__label">{{titles.shortDescription}}</div>
<div class="field__wrap">
<vue-redactor :value="course.short_description"
v-on:update:value="(value) => { this.course.short_description = value; }" />
</div>
</div>
</div>
<div class="info__foot" v-if="!live">
<div class="info__field field field_info info__field--light"
v-bind:class="{ error: ($v.course.category.$dirty || showErrors) && $v.course.category.$invalid }">
<div class="field__label field__label_gray">КАТЕГОРИЯ</div>
<div class="field__wrap">
<lil-select :value.sync="course.category" :options="categoryOptions"
<div class="courses__details">
<div class="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="Выберите категорию"/>
</div>
</div>
<div class="info__field field field_info"
v-bind:class="{ error: ($v.course.duration.$dirty || showErrors) && $v.course.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.duration"
@input="$v.course.duration.$touch()">
<button disabled class="field__append">{{pluralize(course.duration, ['день', 'дня', 'дней'])}}</button>
</div>
</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"
rows="1"
:title="titles.courseTitle"
v-autosize="course.title"
@change="onCourseNameInput"
v-model="course.title"
placeholder="Добавить заголовок"></textarea>
</div>
<div class="courses__content field" 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>
@ -90,6 +65,16 @@
</div>
</div> -->
<div class="info__field field field_info" v-if="!live"
v-bind:class="{ error: ($v.course.duration.$dirty || showErrors) && $v.course.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.duration"
@input="$v.course.duration.$touch()">
<button disabled class="field__append">{{pluralize(course.duration, ['день', 'дня', 'дней'])}}</button>
</div>
</div>
<div v-if="!live" class="info__field field">
<div class="field__label field__label_gray">ДОСТУП</div>
<div class="field__wrap">
@ -267,6 +252,7 @@
users: null,
ROLE_ADMIN: ROLE_ADMIN,
slugChanged: false,
defaultCover: '/img/no_cover.png',
course: {
title: '',
status: null,
@ -444,6 +430,16 @@
}
},
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();
@ -1005,9 +1001,6 @@
// this.updateViewSection(window.location);
},
computed: {
coverBackgroundStyle() {
return this.course.coverImage ? `background-image: url(${this.course.coverImage});` : '';
},
displayPrice: {
get: function () {
return this.course.is_paid ? (this.course.price || '') : '';
@ -1175,10 +1168,67 @@
overflow: scroll;
}
.field_short_description .redactor-box {
.courses__item {
flex: 0 0 300px;
}
.courses__item .field {
margin-bottom: 0;
}
.courses__content .redactor-box {
overflow-x: visible;
overflow-y: auto;
max-height: 200px;
background: none;
margin-top: 10px;
}
.courses__content .redactor-layer{
background: none;
}
.courses__theme {
flex: 1;
}
.courses__price {
margin-left: 20px;
}
.courses__preview {
.upload {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.upload__title {
color: #888888;
font-size: 16px;
margin-top: 100px;
width: 100%;
text-align: center;
}
.upload__file {
width: 100%;
height: 100%;
}
}
.course-delete-cover {
left: 5px;
position: absolute;
bottom: 3px;
}
.select__head {
font-size: inherit;
line-height: inherit;
height: auto;
}
</style>

@ -12,7 +12,7 @@
<div class="kit__gallery">
<div class="kit__preview" v-for="(image, index) in images" v-bind:class="{ 'kit__preview--loading': image.loading }">
<img :src="image.image_thumbnail_url" class="kit__pic">
<button type="button" @click="onRemoveImage(index)">
<button class="kit__delete-photo" type="button" @click="onRemoveImage(index)">
<svg class="icon icon-delete">
<use xlink:href="/static/img/sprite.svg#icon-delete"></use>
</svg>

@ -61,7 +61,7 @@ const app = new Vue({
if(this.urlIs('userProfile')){
if(window.location.hash){
$(document).ready(() => {
$(`[data-anchor=${window.location.hash.slice(1)}]`).click();
$(`[href="${window.location.hash}"]`).click();
});
}
}

@ -2183,11 +2183,13 @@ a.grey-link
color: $pink
border-bottom: 1px $pink solid
.error.field .redactor-box
border-bottom: 1px $pink solid
.info__field--light
.select
.select__head
color: #525252
font-size: 15px
&:after
border-color: #525252 transparent transparent transparent
&.selected
@ -3278,6 +3280,7 @@ a.grey-link
justify-content: center
&__btn
height: 56px
line-height: 56px
border-bottom: 1px solid $border
+fb
font-size: 12px
@ -3488,22 +3491,10 @@ a.grey-link
&__section
display: flex
position: relative
background-position: 50% 50%
background-size: cover
flex: 0 0 calc(50% + 169px)
flex: 0 0 50%
justify-content: flex-end
z-index: 4
&:before
content: ''
position: absolute
top: 0
left: 0
width: 100%
height: 100%
background-image: linear-gradient(135deg, rgba(255, 226, 235, 0.75) 0%, rgba(216, 245, 246, 0.75) 100%)
z-index: -2
&__sidebar
flex: 0 0 calc(50% - 169px)
flex: 0 0 50%
&__main
display: flex
max-width: 675px
@ -3675,6 +3666,10 @@ a.grey-link
flex: 0 0 140px
+m
flex: 0 0 110px
&__delete-photo
position: absolute
bottom: 2px
left: 3px
&__photo
display: flex
position: relative
@ -3720,6 +3715,7 @@ a.grey-link
flex-wrap: wrap
&__gallery &__photo,
&__preview
position: relative
margin: 0 10px 20px
flex: 0 0 calc(25% - 20px)
&--loading
@ -3728,6 +3724,9 @@ a.grey-link
display: block
width: 100%
object-fit: contain
transform: translateY(-50%)
top: 50%
position: relative
&__theme
margin-bottom: 30px
padding-bottom: 5px

Loading…
Cancel
Save