LIL-227 LIL-296 LIL-297

remotes/origin/hasaccess
Vitaly Baev 8 years ago
parent 96160898a5
commit cf32370b6d
  1. 7
      web/build/img/sprite.svg
  2. 3
      web/package.json
  3. 116
      web/src/components/CourseRedactor.vue
  4. 5
      web/src/components/blocks/BlockAdd.vue
  5. 7
      web/src/components/blocks/BlockText.vue
  6. 18
      web/src/icons/hamburger.svg
  7. 1
      web/src/js/app.js
  8. 13
      web/src/js/modules/api.js
  9. 14
      web/src/js/modules/notification.js
  10. 472
      web/src/sass/_common.sass
  11. 33
      web/src/sass/components/notification.scss
  12. 5
      web/src/sass/generated/_sprite-svg.scss

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs>
<path id="a" d="M0 0h15v-2H0v2z"/>
<path id="a" fill-rule="evenodd" d="M12.5 0C3.846 0 0 7 0 7s3.846 7 12.5 7S25 7 25 7s-3.846-7-12.5-7zm0 1C4.808 1 1.154 7 1.154 7s3.654 6 11.346 6 11.346-6 11.346-6S20.192 1 12.5 1zm0 10c2.124 0 3.846-1.79 3.846-4S14.624 3 12.5 3 8.654 4.79 8.654 7s1.722 4 3.846 4zm0-1c1.593 0 2.885-1.343 2.885-3S14.093 4 12.5 4c-1.593 0-2.885 1.343-2.885 3s1.292 3 2.885 3zm0-2c.531 0 .961-.448.961-1s-.43-1-.961-1c-.531 0-.961.448-.961 1s.43 1 .961 1z"/>
<path id="a" fill-rule="evenodd" d="M4.912 13.12C1.555 11.173 0 8.5 0 8.5s3.846-6.611 12.5-6.611c1.254 0 2.408.139 3.463.376l-.817.803a14.781 14.781 0 0 0-2.646-.235C4.808 2.833 1.154 8.5 1.154 8.5s1.456 2.259 4.466 3.924l-.708.696zm4.125 1.615c1.055.237 2.209.376 3.463.376C21.154 15.111 25 8.5 25 8.5s-1.555-2.673-4.912-4.62l-.708.696C22.39 6.24 23.846 8.5 23.846 8.5s-3.654 5.667-11.346 5.667c-.942 0-1.824-.085-2.646-.235l-.817.803zM16.25 7.65c.064.273.097.557.097.849 0 2.086-1.722 3.778-3.846 3.778-.297 0-.586-.033-.864-.096l.864-.849c.738 0 1.476-.276 2.04-.83a2.799 2.799 0 0 0 .845-2.003l.864-.849zm-2.885-2.833a3.925 3.925 0 0 0-.864-.096c-2.124 0-3.846 1.692-3.846 3.778 0 .292.034.576.097.849l.864-.849c0-.725.282-1.45.845-2.003a2.902 2.902 0 0 1 2.04-.83l.864-.85zM20.192 0L3.846 16.056l.962.944L21.154.944 20.192 0z"/>
@ -24,6 +26,11 @@
<path fill-rule="evenodd" d="M6.821 20v-9h2.733L10 7H6.821V5.052C6.821 4.022 6.848 3 8.287 3h1.458V.14c0-.043-1.253-.14-2.52-.14C4.58 0 2.924 1.657 2.924 4.7V7H0v4h2.923v9h3.898z"/>
</symbol><symbol id="icon-fb" viewBox="0 0 8 18">
<path d="M2 7.5H0v-1h2v-.505A5.493 5.493 0 0 1 7.495.5v1A4.493 4.493 0 0 0 3 5.995V6.5h3v1H3v10H2v-10z"/>
</symbol><symbol id="icon-hamburger" viewBox="0 0 15 12">
<use xlink:href="#a" transform="translate(0 12)"/>
<use xlink:href="#a" transform="translate(0 7)"/>
<use xlink:href="#a" transform="translate(0 2)"/>
</symbol><symbol id="icon-image-text" viewBox="0 0 31 15">
<path fill-rule="evenodd" d="M14 13.295V1H1v8.294l4.505-4.501L14 13.295zm-.709.705L5.505 6.207 1 10.707V14h12.291zm13.229 0h-1.66V2.14h-4.22V.66h10.12v1.48h-4.24V14zM0 0h15v15H0V0zm10.5 6.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0-1a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
</symbol><symbol id="icon-image" viewBox="0 0 22 22">

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

@ -65,9 +65,12 @@
"owl.carousel": "^2.2.0",
"slugify": "^1.2.9",
"smooth-scroll": "^12.1.5",
"sortablejs": "^1.7.0",
"uuid": "^3.2.1",
"validator": "^9.2.0",
"vue": "^2.5.13",
"vue-autosize": "^1.0.2",
"vuedraggable": "^2.16.0",
"vuejs-datepicker": "^0.9.25",
"vuelidate": "^0.6.1"
}

@ -139,7 +139,7 @@
<div 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' }"
type="button" @click="viewSection = 'course'">Описание
type="button" @click="showCourse">Описание
курса
</button>
<button class="kit__btn btn btn_lg"
@ -151,41 +151,43 @@
</button>
</div>
<div v-if="viewSection === 'course'" class="kit__body">
<div v-for="(block, index) in course.content">
<block-text v-if="block.type === 'text'"
:index="index"
:title.sync="block.data.title"
:text.sync="block.data.text"
v-on:remove="onBlockRemoved"
:access-token="accessToken"/>
<block-image-text v-if="block.type === 'image-text'"
:index="index"
:title.sync="block.data.title"
:text.sync="block.data.text"
:image-id.sync="block.data.image_id"
:image-url.sync="block.data.image_url"
v-on:remove="onBlockRemoved"
:access-token="accessToken"/>
<block-image v-if="block.type === 'image'"
:index="index"
:title.sync="block.data.title"
:image-id.sync="block.data.image_id"
:image-url.sync="block.data.image_url"
v-on:remove="onBlockRemoved"
:access-token="accessToken"/>
<block-images v-if="block.type === 'images'"
<vue-draggable v-model="course.content" @start="drag=true" @end="drag=false" :options="{ handle: '.sortable__handle' }">
<div v-for="(block, index) in course.content" :key="block.data.id ? block.data.id : block.data.guid">
<block-text v-if="block.type === 'text'"
:index="index"
:title.sync="block.data.title"
:text.sync="block.data.text"
:images.sync="block.data.images"
v-on:remove="onBlockRemoved"
:access-token="accessToken"/>
<block-video v-if="block.type === 'video'"
:index="index"
:title.sync="block.data.title"
v-on:remove="onBlockRemoved"
:video-url.sync="block.data.video_url"/>
</div>
<block-image-text v-if="block.type === 'image-text'"
:index="index"
:title.sync="block.data.title"
:text.sync="block.data.text"
:image-id.sync="block.data.image_id"
:image-url.sync="block.data.image_url"
v-on:remove="onBlockRemoved"
:access-token="accessToken"/>
<block-image v-if="block.type === 'image'"
:index="index"
:title.sync="block.data.title"
:image-id.sync="block.data.image_id"
:image-url.sync="block.data.image_url"
v-on:remove="onBlockRemoved"
:access-token="accessToken"/>
<block-images v-if="block.type === 'images'"
:index="index"
:title.sync="block.data.title"
:text.sync="block.data.text"
:images.sync="block.data.images"
v-on:remove="onBlockRemoved"
:access-token="accessToken"/>
<block-video v-if="block.type === 'video'"
:index="index"
:title.sync="block.data.title"
v-on:remove="onBlockRemoved"
:video-url.sync="block.data.video_url"/>
</div>
</vue-draggable>
<block-add v-on:added="onBlockAdded"/>
@ -257,6 +259,11 @@
import $ from 'jquery';
import {required, minValue, numeric } from 'vuelidate/lib/validators'
import slugify from 'slugify';
import Draggable from 'vuedraggable';
import {showNotification} from "../js/modules/notification";
import createHistory from "history/createBrowserHistory";
const history = createHistory();
export default {
name: "course-redactor",
@ -422,9 +429,21 @@
},
editLesson(lessonIndex) {
this.currentLesson = this.lessons[lessonIndex];
if (this.viewSection !== 'lessons-edit') {
history.push("/course/create/lessons/new");
}
this.viewSection = 'lessons-edit';
},
showCourse() {
if (this.viewSection !== 'course') {
history.push("/course/create");
}
this.viewSection = 'course'
},
showLessons() {
if (this.viewSection !== 'lessons') {
history.push("/course/create/lessons");
}
this.viewSection = 'lessons';
},
addLesson() {
@ -434,6 +453,9 @@
course_id: this.course.id,
content: [],
};
if (this.viewSection !== 'lessons-edit') {
history.push("/course/create/lessons/new");
}
this.viewSection = 'lessons-edit';
window.scrollTo(0, 0);
},
@ -515,6 +537,7 @@
onCoursePublish() {
this.showErrors = true;
if (this.$v.$invalid) {
showNotification("error", "Заполните все необходимые поля");
return;
}
const publishButton = $('#course-redactor__publish-button');
@ -583,6 +606,17 @@
}
},
mounted() {
// 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';
}
});
api.getCategories(this.accessToken)
.then((response) => {
if (response.data) {
@ -677,6 +711,9 @@
return `https://lil.city/course/${suffix}`;
},
},
beforeDestroy() {
this.unlisten();
},
watch: {
'course': {
handler: function (newValue, oldValue) {
@ -707,6 +744,7 @@
'block-images': BlockImages,
'block-video': BlockVideo,
'lesson-redactor': LessonRedactor,
'vue-draggable': Draggable,
}
}
</script>
@ -776,4 +814,18 @@
width: 140px;
height: 140px;
}
</style>
.kit__section-remove {
button.sortable__handle {
margin-right: 10px;
cursor: -webkit-grab;
cursor: grab;
svg.icon-hamburger {
width: 1em;
height: 1em;
}
}
}
</style>

@ -51,6 +51,8 @@
</template>
<script>
import uuidv4 from 'uuid/v4';
export default {
name: "block-add",
data() {
@ -60,6 +62,7 @@
},
methods: {
add(blockData) {
blockData.uuid = uuidv4();
this.isOpen = false;
this.$emit('added', blockData)
},
@ -118,4 +121,4 @@
<style scoped>
</style>
</style>

@ -1,6 +1,11 @@
<template>
<div class="kit__section kit__section--block">
<div class="kit__section-remove">
<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" @click="onRemove">
<svg class="icon icon-delete">
<use xlink:href="/static/img/sprite.svg#icon-delete"></use>
@ -45,4 +50,4 @@
'vue-redactor': VueRedactor,
}
}
</script>
</script>

@ -0,0 +1,18 @@
<svg width="15" height="12" viewBox="0 0 15 12" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Canvas" transform="translate(-249 99)">
<g id="hamburger">
<g id="Line">
<use xlink:href="#path0_stroke" transform="translate(249 -87)" fill="#C8C8C8"/>
</g>
<g id="Line">
<use xlink:href="#path0_stroke" transform="translate(249 -92)" fill="#C8C8C8"/>
</g>
<g id="Line">
<use xlink:href="#path0_stroke" transform="translate(249 -97)" fill="#C8C8C8"/>
</g>
</g>
</g>
<defs>
<path id="path0_stroke" d="M 0 0L 15 0L 15 -2L 0 -2L 0 0Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 597 B

@ -13,6 +13,7 @@ import "./modules/courses";
import "./modules/comments";
import "./modules/password-show";
import "./modules/profile";
import "./modules/notification";
import "./modules/mixpanel";
import "../sass/app.sass";

@ -81,8 +81,10 @@ export const api = {
if (block.type === 'text') {
return {
'type': 'text',
'uuid': block.uuid,
'data': {
'id': block.data.id ? block.data.id : null,
'uuid': block.uuid,
'position': ++index,
'title': block.data.title,
'txt': block.data.text,
@ -93,6 +95,7 @@ export const api = {
'type': 'image',
'data': {
'id': block.data.id ? block.data.id : null,
'uuid': block.data.uuid,
'position': ++index,
'title': block.data.title,
'img': block.data.image_id,
@ -103,6 +106,7 @@ export const api = {
'type': 'image-text',
'data': {
'id': block.data.id ? block.data.id : null,
'uuid': block.data.uuid,
'position': ++index,
'title': block.data.title,
'img': block.data.image_id,
@ -114,6 +118,7 @@ export const api = {
'type': 'images',
'data': {
'id': block.data.id ? block.data.id : null,
'uuid': block.data.uuid,
'position': ++index,
'title': block.data.title,
'images': block.data.images.map((galleryImage) => {
@ -129,6 +134,7 @@ export const api = {
'type': 'video',
'data': {
'id': block.data.id ? block.data.id : null,
'uuid': block.data.uuid,
'position': ++index,
'title': block.data.title,
'url': block.data.video_url,
@ -271,6 +277,7 @@ export const api = {
'type': 'text',
'data': {
'id': contentItem.id ? contentItem.id : null,
'uuid': contentItem.uuid,
'title': contentItem.title,
'text': contentItem.txt,
}
@ -280,6 +287,7 @@ export const api = {
'type': 'image',
'data': {
'id': contentItem.id ? contentItem.id : null,
'uuid': contentItem.uuid,
'title': contentItem.title,
'image_id': contentItem.img.id,
'image_url': contentItem.img.image,
@ -290,6 +298,7 @@ export const api = {
'type': 'image-text',
'data': {
'id': contentItem.id ? contentItem.id : null,
'uuid': contentItem.uuid,
'title': contentItem.title,
'image_id': contentItem.img.id,
'image_url': contentItem.img.image,
@ -301,6 +310,7 @@ export const api = {
'type': 'images',
'data': {
'id': contentItem.id ? contentItem.id : null,
'uuid': contentItem.uuid,
'title': contentItem.title,
'images': contentItem.gallery_images.map((galleryImage) => {
return {
@ -316,6 +326,7 @@ export const api = {
'type': 'video',
'data': {
'id': contentItem.id ? contentItem.id : null,
'uuid': contentItem.uuid,
'title': contentItem.title,
'video_url': contentItem.url,
}
@ -407,4 +418,4 @@ export const api = {
}
});
}
};
};

@ -0,0 +1,14 @@
import $ from 'jquery';
import '../../sass/components/notification.scss';
export function showNotification(style, text) {
let htmlNode = document.createElement('div');
let htmlElement = $(htmlNode).addClass('notification').addClass(`notification--${style}`).text(text).appendTo($('body'));
setTimeout(() => {
htmlElement.fadeOut(400, () => {
htmlElement.remove();
})
}, 3500);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,33 @@
.notification {
min-width: 380px;
box-sizing: border-box;
border-radius: 4px;
border-width: 1px;
border-style: solid;
border-color: #ebeef5;
position: fixed;
left: 50%;
top: 20px;
transform: translateX(-50%);
background-color: #edf2fc;
transition: opacity 0.3s, transform .4s;
overflow: hidden;
padding: 15px 15px 15px 20px;
display: flex;
align-items: center;
z-index: 1000;
&--success {
background: #53CF86;
color: #fff;
border: none;
box-shadow: 0 4px 15px rgba(0, 196, 83, 0.31);
}
&--error {
background: #D12424;
color: #fff;
border: none;
box-shadow: 0 4px 15px rgba(255, 36, 36, 0.51);
}
}

@ -53,6 +53,11 @@
height: 1em;
fill: #1C2635;
}
.icon-hamburger {
width: 1.25em;
height: 1em;
fill: #C8C8C8;
}
.icon-image-text {
width: 2.07em;
height: 1em;

Loading…
Cancel
Save