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.
231 lines
7.5 KiB
231 lines
7.5 KiB
<template>
|
|
<form @submit.prevent="save">
|
|
<div class="info">
|
|
<div class="info__section" :style="coverBackgroundStyle">
|
|
<div class="info__main">
|
|
<div class="info__head">
|
|
<div class="info__upload upload">
|
|
Загрузить фон
|
|
<input type="file" class="upload__file" @change="onCoverImageSelected">
|
|
</div>
|
|
</div>
|
|
<div class="info__title">
|
|
<div class="info__field field field_info"
|
|
v-bind:class="{ error: $v.contest.title.$dirty && $v.contest.title.$invalid }">
|
|
<div class="field__label">Название</div>
|
|
<div class="field__wrap">
|
|
<textarea class="field__textarea"
|
|
rows="1"
|
|
v-autosize="contest.title"
|
|
@change="onTitleInput"
|
|
v-model="contest.title"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="info__field field field_info field_short_description">
|
|
<div class="field__label">Описание</div>
|
|
<div class="field__wrap">
|
|
<textarea class="field__textarea"
|
|
v-autosize="contest.description"
|
|
v-model="contest.description"></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="info__foot">
|
|
<div class="info__field field">
|
|
<div class="field__label field__label_gray">ССЫЛКА</div>
|
|
<div class="field__wrap">
|
|
<input type="text" class="field__input" v-model="contest.slug" @input="slugChanged = true">
|
|
</div>
|
|
<div class="field__wrap field__wrap--additional">{{ contestFullUrl }}</div>
|
|
</div>
|
|
<div class="info__field field">
|
|
<div class="field__label">ДАТА НАЧАЛА</div>
|
|
<div class="field__wrap">
|
|
<vue-datepicker input-class="field__input" v-model="contest.date_start" language="ru" format="dd/MM/yyyy"/>
|
|
</div>
|
|
</div>
|
|
<div class="info__field field">
|
|
<div class="field__label">ДАТА ОКОНЧАНИЯ</div>
|
|
<div class="field__wrap">
|
|
<vue-datepicker input-class="field__input" v-model="contest.date_end" language="ru" format="dd/MM/yyyy"/>
|
|
</div>
|
|
</div>
|
|
<button type="submit">Save</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="info__sidebar">
|
|
<div class="info__wrap">
|
|
<div class="info__fieldset">
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="section">
|
|
<div class="section__center center">
|
|
<div class="kit">
|
|
<div class="kit__body">
|
|
<block-content :content.sync="contest.content"></block-content>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
|
|
<script>
|
|
import {api} from "../js/modules/api";
|
|
import DatePicker from 'vuejs-datepicker';
|
|
import BlockContent from './blocks/BlockContent'
|
|
import slugify from 'slugify';
|
|
import {required, minValue, numeric, url } from 'vuelidate/lib/validators'
|
|
import _ from 'lodash';
|
|
import moment from 'moment'
|
|
|
|
export default {
|
|
name: 'contest-redactor',
|
|
props: ["contestId"],
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
slugChanged: false,
|
|
contest: {
|
|
coverImage: '',
|
|
coverImageId: null,
|
|
|
|
title: '',
|
|
description: '',
|
|
content: [],
|
|
date_start: '',
|
|
date_end: '',
|
|
slug: '',
|
|
active: true,
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
accessToken() {
|
|
return window.LIL_STORE.accessToken;
|
|
},
|
|
coverBackgroundStyle() {
|
|
return this.contest.coverImage ? `background-image: url(${this.contest.coverImage});` : '';
|
|
},
|
|
contestFullUrl() {
|
|
return `https://lil.city/contest/${this.contest.slug}`;
|
|
},
|
|
},
|
|
|
|
validations() {
|
|
return {
|
|
contest: {
|
|
title: {
|
|
required
|
|
},
|
|
},
|
|
};
|
|
},
|
|
mounted() {
|
|
if (this.contestId) {
|
|
this.load();
|
|
}
|
|
},
|
|
methods: {
|
|
onTitleInput() {
|
|
this.$v.contest.title.$touch();
|
|
if (!this.slugChanged) {
|
|
this.contest.slug = slugify(this.contest.title);
|
|
}
|
|
},
|
|
onCoverImageSelected(event) {
|
|
let file = event.target.files[0];
|
|
let reader = new FileReader();
|
|
reader.onload = () => {
|
|
this.$set(this.contest, 'coverImage', reader.result);
|
|
api.uploadImage(reader.result, this.accessToken)
|
|
.then((response) => {
|
|
this.contest.coverImageId = response.data.id;
|
|
})
|
|
.catch((error) => {
|
|
//console.log('error', error);
|
|
});
|
|
};
|
|
if (file) {
|
|
reader.readAsDataURL(file);
|
|
}
|
|
},
|
|
|
|
processContestJson(data) {
|
|
this.contest = {
|
|
coverImage: data.cover && data.cover.image || null,
|
|
coverImageId: data.cover && data.cover.id || null,
|
|
|
|
id: data.id,
|
|
title: data.title,
|
|
description: data.description,
|
|
content: api.convertContentJson(data.content),
|
|
date_start: data.date_start,
|
|
date_end: data.date_end,
|
|
slug: data.slug,
|
|
active: data.active,
|
|
|
|
};
|
|
},
|
|
load() {
|
|
this.loading = true;
|
|
const request = api.get(`/api/v1/contests/${this.contestId}/`, {
|
|
headers: {
|
|
'Authorization': `Token ${window.LIL_STORE.accessToken}`,
|
|
}
|
|
});
|
|
request
|
|
.then((response) => {
|
|
this.processContestJson(response.data);
|
|
this.$nextTick(() => {
|
|
this.loading = false;
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
this.loading = false;
|
|
});
|
|
|
|
return request;
|
|
},
|
|
save() {
|
|
let data = _.pick(this.contest, ['title', 'description', 'slug', 'active']);
|
|
data.date_start = data.date_start ? moment(data.date_start).format('MM-DD-YYYY') : null;
|
|
data.date_end = data.date_end ? moment(data.date_end).format('MM-DD-YYYY') : null;
|
|
data.cover = this.contest.coverImageId || '';
|
|
data.content = api.convertContentJson(this.contest.content, true);
|
|
|
|
const request = this.contest.id
|
|
? api.put(`/api/v1/contests/${this.contest.id}/`, data, {
|
|
headers: {
|
|
'Authorization': `Token ${window.LIL_STORE.accessToken}`,
|
|
}
|
|
})
|
|
: api.post('/api/v1/contests/', data, {
|
|
headers: {
|
|
'Authorization': `Token ${window.LIL_STORE.accessToken}`,
|
|
}
|
|
});
|
|
request.then((response) => {
|
|
if(this.contest.id) {
|
|
this.contest = this.processContestJson(response.data);
|
|
}
|
|
else {
|
|
window.location.href = `/contest/${response.data.id}/edit`;
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
//this.contestSaving = false;
|
|
});
|
|
|
|
}
|
|
},
|
|
components: {
|
|
BlockContent,
|
|
'vue-datepicker': DatePicker,
|
|
}
|
|
};
|
|
</script>
|
|
|