Update templates
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
{% extends "skeleton.html" %}
|
||||
{% block body %}
|
||||
{% block content %}
|
||||
|
||||
<h3>Профиль</h3>
|
||||
<hr />
|
||||
|
||||
<p>Зарегистрирован: {{ user.created.strftime('%Y-%m-%d') }}</p>
|
||||
|
||||
{% endblock body %}
|
||||
{% endblock content %}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "skeleton.html" %}
|
||||
{% block body %}
|
||||
{% block content %}
|
||||
|
||||
{% raw %}
|
||||
<h3>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "skeleton.html" %}
|
||||
{% block body %}
|
||||
{% block content %}
|
||||
|
||||
<h3>
|
||||
<div class="btn btn-outline-success float-right" v-on:click="showFormNewTag"><i class="fa fa-plus"></i></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "skeleton.html" %}
|
||||
{% block body %}
|
||||
{% block content %}
|
||||
|
||||
<h3>Список пользователей</h3>
|
||||
<hr />
|
||||
|
||||
113
myapp/static/components/pagination.js
Normal file
113
myapp/static/components/pagination.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
<pagination-component v-bind:pagination="pagination" v-bind:click-handler="getRecipes"></pagination-component>
|
||||
<script type="text/javascript" src="/static/components/pagination.js"></script>
|
||||
|
||||
Vue
|
||||
...
|
||||
data: {
|
||||
pagination: {
|
||||
page: 1,
|
||||
per_page: {{ per_page }},
|
||||
size: {{ pagedata['count'] }}
|
||||
},
|
||||
}
|
||||
...
|
||||
|
||||
Flask
|
||||
pagedata['pagination'] = {
|
||||
"page": page,
|
||||
"per_page": app.config['ITEMS_ON_PAGE'],
|
||||
"size": 0
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
let paginationTemplate = `<div class="row">
|
||||
<div class="col py-2 text-center">
|
||||
<div class="btn btn-outline-secondary" v-if="pages()<=1">...</div>
|
||||
|
||||
<template v-else>
|
||||
<button type="button" class="btn btn-outline-secondary pull-left" v-if="has_prev" v-on:click="handlePageSelected(pagination.page-1)">Предыдущая</button>
|
||||
|
||||
<template v-for="page in iter_pages">
|
||||
<button type="button" class="btn btn-outline-secondary mr-1" v-if="page" v-on:click="handlePageSelected(page)">{{ page }}</button>
|
||||
<div class="btn btn-outline-secondary mr-1" v-else>...</div>
|
||||
</template>
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary float-right" v-if="has_next" v-on:click="handlePageSelected(pagination.page+1)">Следующая</button>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
Vue.component('pagination-component', {
|
||||
template: paginationTemplate,
|
||||
data: function() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
props:{
|
||||
pagination: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: {
|
||||
page: 1,
|
||||
per_page: 25,
|
||||
size: 0
|
||||
}
|
||||
},
|
||||
clickHandler: {
|
||||
type: Function,
|
||||
default: function() { }
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handlePageSelected: function(selected) {
|
||||
/* Установить номер текущей страницы и вызвать функция обновления
|
||||
* страницы
|
||||
*
|
||||
* Аргументы:
|
||||
* selected -- номер страницы
|
||||
*/
|
||||
let vm = this;
|
||||
vm.pagination.page = selected;
|
||||
vm.clickHandler();
|
||||
},
|
||||
pages: function() {
|
||||
let vm = this;
|
||||
return Math.ceil(vm.pagination.size/vm.pagination.per_page);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
has_prev: function() {
|
||||
let vm = this;
|
||||
return vm.pagination.page > 1;
|
||||
},
|
||||
has_next: function() {
|
||||
let vm = this;
|
||||
return vm.pagination.page < vm.pages();
|
||||
},
|
||||
iter_pages: function() {
|
||||
/* */
|
||||
let vm = this;
|
||||
let last = 0;
|
||||
let left_edge=2, left_current=2,
|
||||
right_current=5, right_edge=2;
|
||||
let result = [];
|
||||
for (let num = 1; num < vm.pages()+1; num++) {
|
||||
if (num <= left_edge ||
|
||||
(num > vm.pagination.page - left_current - 1 &&
|
||||
num < vm.pagination.page + right_current) ||
|
||||
num > vm.pages() - right_edge) {
|
||||
if (last + 1 != num) {
|
||||
result.push(null);
|
||||
} else {
|
||||
result.push(num);
|
||||
}
|
||||
last = num
|
||||
}
|
||||
};
|
||||
return result;
|
||||
},
|
||||
}
|
||||
});
|
||||
268
myapp/static/components/tags.js
Normal file
268
myapp/static/components/tags.js
Normal file
@@ -0,0 +1,268 @@
|
||||
var tagsTemplate = `
|
||||
<div>
|
||||
<!-- Начало: Теги -->
|
||||
<div class="row my-3">
|
||||
<div class="col">
|
||||
<div class="btn mb-1"><i class="fa fa-tags"></i></div>
|
||||
|
||||
<div class="btn btn-outline-success mb-1" v-on:click="showPanel(panels.standart)"><i class="fa fa-plus"></i></div>
|
||||
|
||||
<div class="btn-group mr-2 mb-1" v-for="(tag, index) in sortedTags">
|
||||
<a class="btn btn-outline-secondary text-monospace" :href="'/tag/' + tag.id">{{ tag.name }}</a>
|
||||
<div class="btn btn-outline-danger" v-on:click="removeTag(tag.id)"><i class="fa fa-remove"></i></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3" v-if="panels.standart.visible">
|
||||
<div class="col">
|
||||
|
||||
<div class="input-group">
|
||||
<input v-model="newtag" v-on:keyup.13="addTag" class="form-control" />
|
||||
<div class="input-group-append">
|
||||
<div class="btn btn-outline-success" v-on:click="addTag"><i class="fa fa-save"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<template v-for="(tags, key, index) in groups">
|
||||
|
||||
<a class="btn btn-outline-secondary mt-2 mr-2" v-if="(index % 2)===0" :href="'#' + index">{{ key }}</a>
|
||||
<a class="btn btn-outline-primary mt-2 mr-2" v-else :href="'#' + index">{{ key }}</a>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Начало: Форма добавления нового тега -->
|
||||
<div class="row" v-if="panels.new.visible">
|
||||
<div class="col py-2">
|
||||
Добавить новый тег [<b id="newTag">{{ newtag }}</b>]?
|
||||
|
||||
<div class="row">
|
||||
<div class="col py-2">
|
||||
<div class="btn btn-outline-danger" v-on:click="cancelNewTag">Отмена</div>
|
||||
<div class="btn btn-outline-success float-right" v-on:click="addNewTag">Добавить</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- Конец: Форма добавления нового тега -->
|
||||
|
||||
<div class="row mt-3" v-for="(tags, key, index) in groups">
|
||||
<div class="col pr-0">
|
||||
<a :name="index" class="btn btn-outline-danger mr-2 mb-1">{{ key }}</a>
|
||||
<template v-for="(tag, tagIdx) in tags">
|
||||
<div class="btn btn-outline-secondary mr-2 mb-1" v-if="!tag_ids.includes(tag.id)" v-on:click="tag_add_to_node(tag)">{{ tag.name }}</div>
|
||||
<div class="btn btn-primary mr-2 mb-1" v-else v-on:click="removeTag(tag.id)">{{ tag.name }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- Конец: Теги -->
|
||||
</div>`;
|
||||
|
||||
Vue.component('tags-component', {
|
||||
data: function() {
|
||||
return {
|
||||
newtag: '',
|
||||
groups: {},
|
||||
forms: {
|
||||
modal: false,
|
||||
panel: false
|
||||
},
|
||||
panels: {
|
||||
standart: {
|
||||
visible: false
|
||||
},
|
||||
new: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
props: ['tags', 'node', 'url'],
|
||||
template: tagsTemplate,
|
||||
methods: {
|
||||
arrayRemove: function(arr, value) {
|
||||
/* Удаление элемента из списка */
|
||||
return arr.filter(function(ele){
|
||||
return ele != value;
|
||||
});
|
||||
},
|
||||
removeTag: function (id) {
|
||||
/* Удаление тега из ресурса */
|
||||
let vm = this;
|
||||
var tag = null;
|
||||
for (var i = 0; i < vm.tags.length; i++) {
|
||||
if (id == vm.tags[i].id) {
|
||||
tag = vm.tags[i]
|
||||
}
|
||||
}
|
||||
if (!tag) {return;}
|
||||
axios.post(
|
||||
'/api',
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": 'tag.deleteFrom' + vm.url,
|
||||
"params": {
|
||||
"id": vm.node,
|
||||
"tag": tag.id
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
).then(
|
||||
function(response) {
|
||||
if ('result' in response.data) {
|
||||
vm.tags = vm.arrayRemove(vm.tags, tag);
|
||||
} else if ('error' in response.data) {
|
||||
console.log(response.data);
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
addTag: function () {
|
||||
/* Добавить тег к ресурсу */
|
||||
let vm = this;
|
||||
var newtag = vm.newtag.trim();
|
||||
vm.newtag = newtag;
|
||||
axios.post(
|
||||
'/api',
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": 'tag.exist',
|
||||
"params": {
|
||||
name: vm.newtag
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
).then(
|
||||
function(response) {
|
||||
if ('result' in response.data) {
|
||||
vm.tag_add_to_node( response.data['result'] );
|
||||
} else if ('error' in response.data) {
|
||||
console.log(response.data);
|
||||
vm.panels.new.visible = true;
|
||||
}
|
||||
}
|
||||
).catch(
|
||||
function (error) {
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
addNewTag:function () {
|
||||
/* Добавление нового тега */
|
||||
let vm = this;
|
||||
axios.post(
|
||||
'/api',
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": 'tag.add',
|
||||
"params": {
|
||||
name: vm.newtag
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
).then(
|
||||
function(response) {
|
||||
if ('result' in response.data) {
|
||||
vm.getTags();
|
||||
vm.tag_add_to_node( response.data['result'] );
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
cancelNewTag:function () {
|
||||
let vm = this;
|
||||
vm.newtag = '';
|
||||
vm.panels.new.visible = false;
|
||||
},
|
||||
// Добавление тега к ресурсу
|
||||
tag_add_to_node: function(tag) {
|
||||
let vm = this;
|
||||
axios.post(
|
||||
'/api',
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": 'tag.addTo' + this.url,
|
||||
"params": {
|
||||
"id": vm.node,
|
||||
"tag": tag.id
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
).then(
|
||||
function(response) {
|
||||
if ('result' in response.data) {
|
||||
vm.tags.push(response.data['result']);
|
||||
vm.newtag = '';
|
||||
vm.panels.new.visible = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
// Получить список тегов
|
||||
getTags: function() {
|
||||
let vm = this;
|
||||
axios.post(
|
||||
'/api',
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": 'tags.groups',
|
||||
"params": {},
|
||||
"id": 1
|
||||
}
|
||||
).then(
|
||||
function(response) {
|
||||
if ('result' in response.data) {
|
||||
vm.groups = response.data['result'];
|
||||
}
|
||||
}
|
||||
).catch(
|
||||
function (error) {
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
showPanel: function(panel) {
|
||||
/* Показать/скрыть панель */
|
||||
panel.visible = !panel.visible;
|
||||
},
|
||||
},
|
||||
mounted: function() {
|
||||
let vm = this;
|
||||
vm.getTags();
|
||||
},
|
||||
computed: {
|
||||
tag_ids: function() {
|
||||
let vm = this;
|
||||
var result = [];
|
||||
for (var i = 0; i < vm.tags.length; i++) {
|
||||
result.push(vm.tags[i].id);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
sortedTags: function() {
|
||||
let vm = this;
|
||||
if (vm.tags === undefined) {return [];}
|
||||
vm.tags.sort(
|
||||
function(a, b) {
|
||||
if (a.name > b.name) {
|
||||
return 1;
|
||||
}
|
||||
if (a.name < b.name) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
return vm.tags;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "skeleton.html" %}
|
||||
{% block body %}
|
||||
{% block content %}
|
||||
|
||||
<h3 class="text-danger">{{ error_code }}: {{ error_message }}</h3>
|
||||
<hr />
|
||||
|
||||
37
myapp/templates/inc/editor.js
Normal file
37
myapp/templates/inc/editor.js
Normal file
@@ -0,0 +1,37 @@
|
||||
{% macro plugin(type="tinymce") -%}
|
||||
{% if type=="tinymce" %}
|
||||
<script type="text/javascript" src="/static/tinymce/tinymce.min.js"></script>
|
||||
{% elif type=="ckeditor" %}
|
||||
<script type="text/javascript" src="/static/ckeditor/ckeditor.js"></script>
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro ckeditor(name) -%}
|
||||
CKEDITOR.replace( '{{ name }}', {
|
||||
customConfig: '/static/js/ckeditor-conf.js'
|
||||
} );
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro tinymce(name) -%}
|
||||
tinymce.init({
|
||||
selector: 'textarea#{{ name }}',
|
||||
height: 400,
|
||||
language: 'ru',
|
||||
plugins: "code link image table",
|
||||
toolbar: "table tabledelete | tableprops tablerowprops tablecellprops | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol"
|
||||
});
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro getValue(name, param, type="tinymce") -%}
|
||||
{% if type=="tinymce" %}
|
||||
let value = tinymce.get("{{ name }}").getContent();
|
||||
if (value != {{ param }}) {
|
||||
{{ param }} = value;
|
||||
}
|
||||
{% elif type=="ckeditor" %}
|
||||
var value = CKEDITOR.instances["{{ name }}"].getData();
|
||||
if (value != {{ param }}) {
|
||||
{{ param }} = value;
|
||||
}
|
||||
{% endif %}
|
||||
{%- endmacro %}
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "skeleton.html" %}
|
||||
{% block body %}
|
||||
{% block content %}
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
<div class="row">
|
||||
<div class="col py-2">
|
||||
|
||||
{% if session.logged_in %}
|
||||
<div class="btn-group float-right">
|
||||
<a class="btn btn-outline-secondary border-0" href="/profile"><i class="fa fa-user"></i></a>
|
||||
<a class="btn btn-outline-danger border-0" href="/logout"><i class="fa fa-sign-out"></i></a>
|
||||
</div>
|
||||
{% else %}
|
||||
<a class="btn btn-outline-success border-0 float-right" href="/login"><i class="fa fa-sign-in"></i></a>
|
||||
{% endif %}
|
||||
|
||||
<a class="btn btn-outline-secondary border-0" href="/"><i class="fa fa-home"></i></a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/page">Статья</a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/pages">Статьи</a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/tags">Метки</a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/users">Пользователи</a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/api/browse">API JSON-RPC</a>
|
||||
|
||||
<a class="btn btn-outline-success border-0 float-right" href="/login"><i class="fa fa-sign-in"></i></a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
{% extends "skeleton.html" %}
|
||||
{% block body %}
|
||||
|
||||
{% raw %}
|
||||
<h3>
|
||||
<div class="btn btn-outline-secondary float-right" v-on:click="showPanel(panels.edit)"><i class="fa fa-edit"></i></div>
|
||||
{{ page.title }}</h3>
|
||||
<hr />
|
||||
|
||||
<div class="row" v-if="panels.edit.visible">
|
||||
<div class="col">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="title">Заголовок</label>
|
||||
<input id="title" name="title" type="text" value="Заголовок страницы" class="form-control" v-model="newPage.title">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="text">Текст</label>
|
||||
<textarea class="form-control" id="text" name="text" v-model="newPage.text"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button class="btn btn-outline-success float-right" v-on:click="send"><i class="fa fa-save-o"></i> Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3" v-if="error">
|
||||
<div class="col bg-danger text-white" v-html="error">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<span v-html="page.text" v-else></span>
|
||||
|
||||
{% endraw %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
<ol class="breadcrumb mt-3">
|
||||
<li class="breadcrumb-item"><a href="/"><i class="fa fa-home"></i></a></li>
|
||||
<li class="breadcrumb-item active">Редактирование страницы</li>
|
||||
</ol>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript" src="/static/ckeditor/ckeditor.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
page: {{ pagedata['page']|tojson|safe }},
|
||||
newPage: {{ pagedata['page']|tojson|safe }},
|
||||
panels: {
|
||||
edit: {
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
error: null
|
||||
},
|
||||
methods: {
|
||||
showPanel: function(panel) {
|
||||
/* Показать/скрыть панель */
|
||||
panel.visible = !panel.visible;
|
||||
},
|
||||
send: function() {
|
||||
let vm = this;
|
||||
var value = CKEDITOR.instances["text"].getData();
|
||||
if (value != vm.newPage.text) {
|
||||
vm.newPage.text = value;
|
||||
}
|
||||
axios.post(
|
||||
'/api',
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": 'page.update',
|
||||
"params": {
|
||||
"title": vm.newPage.title,
|
||||
"text": vm.newPage.text
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
).then(
|
||||
function(response) {
|
||||
if ('result' in response.data) {
|
||||
vm.page = response.data['result'];
|
||||
vm.newPage = vm.page;
|
||||
vm.error = null;
|
||||
} else if ('error' in response.data) {
|
||||
vm.error = response.data['error'].message;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
updated: function() {
|
||||
let vm = this;
|
||||
for(var instanceName in CKEDITOR.instances) {
|
||||
CKEDITOR.instances[instanceName].destroy(true);
|
||||
}
|
||||
if (vm.panels.edit.visible) {
|
||||
CKEDITOR.replace( "text", {
|
||||
customConfig: '/static/js/ckeditor-conf.js'
|
||||
} );
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -7,8 +7,8 @@
|
||||
<div class="container">
|
||||
{% include 'navbar.html' %}
|
||||
|
||||
{% block body %}
|
||||
{% endblock body %}
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{% endblock %}
|
||||
|
||||
16
myapp/templates/user/navbar.html
Normal file
16
myapp/templates/user/navbar.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<div class="row">
|
||||
<div class="col py-2">
|
||||
|
||||
<a class="btn btn-outline-secondary border-0" href="/"><i class="fa fa-home"></i></a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/pages">Статьи</a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/tags">Метки</a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/users">Пользователи</a>
|
||||
<a class="btn btn-outline-secondary border-0" href="/api/browse">API JSON-RPC</a>
|
||||
|
||||
<div class="btn-group float-right">
|
||||
<a class="btn btn-outline-secondary border-0" href="/profile"><i class="fa fa-user"></i></a>
|
||||
<a class="btn btn-outline-danger border-0" href="/logout"><i class="fa fa-sign-out"></i></a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
33
myapp/templates/user/skeleton.html
Normal file
33
myapp/templates/user/skeleton.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
{% include 'header.html' %}
|
||||
<body>
|
||||
<section id="app">
|
||||
|
||||
<div class="container">
|
||||
{% include 'user/navbar.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{% endblock %}
|
||||
|
||||
{% include 'footer.html' %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript">
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{% endblock script %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user