Add tag
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
Flask==1.1.2
|
Flask
|
||||||
Flask-JSONRPC==1.1.0
|
git+https://gitlab.com/RemiZOffAlex/jsonrpc@master#egg=jsonrpc
|
||||||
alembic==1.4.2
|
alembic
|
||||||
SQLAlchemy==1.3.17
|
SQLAlchemy
|
||||||
SQLAlchemy-Utils==0.36.6
|
SQLAlchemy-Utils
|
||||||
flake8==3.8.3
|
flake8
|
||||||
gunicorn==20.0.4
|
gunicorn
|
||||||
psycopg2-binary==2.8.5
|
psycopg2-binary
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
<meta name="author" content="Ремизов Александр" />
|
<meta name="author" content="Ремизов Александр" />
|
||||||
<meta name="copyright" lang="ru" content="RemiZOffAlex" />
|
<meta name="copyright" lang="ru" content="RemiZOffAlex" />
|
||||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||||
|
|||||||
@@ -4,7 +4,23 @@ function arrayRemove(arr, value) {
|
|||||||
return ele.id != value.id;
|
return ele.id != value.id;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
function arrayRemoveByID(arr, value) {
|
||||||
|
/* Удаление элемента из списка */
|
||||||
|
return arr.filter(function (ele) {
|
||||||
|
return ele.id != value.id;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
function arrayRemoveByItem(arr, value) {
|
||||||
|
/* Удаление элемента из списка */
|
||||||
|
return arr.filter(function (ele) {
|
||||||
|
return ele != value;
|
||||||
|
});
|
||||||
|
};
|
||||||
function panel_show(panel) {
|
function panel_show(panel) {
|
||||||
/* Показать/скрыть панель */
|
/* Показать/скрыть панель */
|
||||||
panel.visible = !panel.visible;
|
panel.visible = !panel.visible;
|
||||||
};
|
};
|
||||||
|
function get_id() {
|
||||||
|
/* Получить рандомный ID */
|
||||||
|
return Math.random().toString(16).slice(2);
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,17 +3,7 @@
|
|||||||
{% include 'header.html' %}
|
{% include 'header.html' %}
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<section id="app" class="container">
|
<section id="app" class="container"></section>
|
||||||
{% include '/private/navbar.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% endblock content %}
|
|
||||||
|
|
||||||
{% block breadcrumb %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% include 'footer.html' %}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="{{ STATIC }}/tinymce/tinymce.min.js"></script>
|
<script type="text/javascript" src="{{ STATIC }}/tinymce/tinymce.min.js"></script>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ let MenuGeneral = {
|
|||||||
m(m.route.Link, {class: 'btn btn-outline-secondary', href: '/'}, m('i', {class: 'fa fa-home'})),
|
m(m.route.Link, {class: 'btn btn-outline-secondary', href: '/'}, m('i', {class: 'fa fa-home'})),
|
||||||
m(m.route.Link, {class: 'btn btn-outline-secondary border-0', href: '/pages'}, 'Статьи'),
|
m(m.route.Link, {class: 'btn btn-outline-secondary border-0', href: '/pages'}, 'Статьи'),
|
||||||
m(m.route.Link, {class: 'btn btn-outline-secondary border-0', href: '/tags'}, 'Метки'),
|
m(m.route.Link, {class: 'btn btn-outline-secondary border-0', href: '/tags'}, 'Метки'),
|
||||||
m(m.route.Link, {class: 'btn btn-outline-secondary border-0', href: '/users'}, 'Пользователи'),
|
|
||||||
m(m.route.Link, {class: 'btn btn-outline-secondary border-0', href: '/api/browse'}, 'API JSON-RPC'),
|
m(m.route.Link, {class: 'btn btn-outline-secondary border-0', href: '/api/browse'}, 'API JSON-RPC'),
|
||||||
m(m.route.Link, {class: 'btn btn-outline-success float-end', href: '/login'}, m('i', {class: 'fa fa-sign-in'})),
|
m(m.route.Link, {class: 'btn btn-outline-success float-end', href: '/login'}, m('i', {class: 'fa fa-sign-in'})),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{% include '/public/domains/auth/inc.j2' %}
|
{% include '/public/domains/auth/inc.j2' %}
|
||||||
{% include '/public/domains/page/inc.j2' %}
|
{% include '/public/domains/page/inc.j2' %}
|
||||||
|
{% include '/public/domains/tag/inc.j2' %}
|
||||||
{% include '/public/domains/user/inc.j2' %}
|
{% include '/public/domains/user/inc.j2' %}
|
||||||
{% include '/public/domains/home.js' %}
|
{% include '/public/domains/home.js' %}
|
||||||
|
|
||||||
|
|||||||
10
myapp/templates/public/domains/tag/inc.j2
Normal file
10
myapp/templates/public/domains/tag/inc.j2
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{% include '/public/domains/tag/tag.js' %}
|
||||||
|
{% include '/public/domains/tag/tags.js' %}
|
||||||
|
|
||||||
|
Object.assign(
|
||||||
|
routes,
|
||||||
|
{
|
||||||
|
"/tag/:id": layout_decorator(Tag),
|
||||||
|
"/tags": layout_decorator(Tags),
|
||||||
|
}
|
||||||
|
);
|
||||||
82
myapp/templates/public/domains/tag/tag.js
Normal file
82
myapp/templates/public/domains/tag/tag.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
function Tag() {
|
||||||
|
let data = {
|
||||||
|
tag: null,
|
||||||
|
menuitem: null,
|
||||||
|
};
|
||||||
|
function breadcrumbs_render() {
|
||||||
|
let result = m('ul', { class: 'breadcrumb mt-2' }, [
|
||||||
|
m('li', { class: 'breadcrumb-item' }, m(m.route.Link, { href: '/' }, m('i', { class: 'fa fa-home' }))),
|
||||||
|
m('li', { class: 'breadcrumb-item' }, m(m.route.Link, { href: '/tags' }, 'Список тегов')),
|
||||||
|
m('li', { class: 'breadcrumb-item active' }, data.tag.name),
|
||||||
|
]);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
function tag_get(id) {
|
||||||
|
m.request({
|
||||||
|
url: '/api',
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": 'tag',
|
||||||
|
"params": {
|
||||||
|
"id": id,
|
||||||
|
"fields": ["id", "name", "description"]
|
||||||
|
},
|
||||||
|
"id": get_id()
|
||||||
|
}
|
||||||
|
}).then(
|
||||||
|
function (response) {
|
||||||
|
if ('result' in response) {
|
||||||
|
data.tag = response['result'];
|
||||||
|
document.title = `${data.tag.name} - ${SETTINGS.TITLE}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
oninit: function (vnode) {
|
||||||
|
console.log('Tag.oninit');
|
||||||
|
tag_get(vnode.attrs.id);
|
||||||
|
},
|
||||||
|
view: function (vnode) {
|
||||||
|
console.log('Tag.view');
|
||||||
|
result = [];
|
||||||
|
if (data.tag != null) {
|
||||||
|
result.push(
|
||||||
|
breadcrumbs_render(),
|
||||||
|
m('div', { class: 'row' },
|
||||||
|
m('div', { class: 'col h1 py-2' }, [
|
||||||
|
m('div', { class: 'btn-group btn-group-lg me-2' },
|
||||||
|
m(m.route.Link, { class: "btn btn-outline-secondary", href: "/tags", title: "Облако тегов" }, m('i', { class: 'fa fa-chevron-left' })),
|
||||||
|
),
|
||||||
|
data.tag.name
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
m('hr'),
|
||||||
|
);
|
||||||
|
|
||||||
|
// result.push(m(MenuTag, {"tag1": data.tag}));
|
||||||
|
result.push({ tag: MenuTag, attrs: { tag: data.tag } });
|
||||||
|
|
||||||
|
result.push(
|
||||||
|
m('div', { class: 'row' }, [
|
||||||
|
m('div', { class: "col-md-4 py-2" },
|
||||||
|
m(m.route.Link, { class: "btn btn-outline-secondary btn-lg w-100", href: `/tag/${data.tag.id}/notes` }, 'Заметки с тегом'),
|
||||||
|
),
|
||||||
|
m('div', { class: "col-md-4 py-2" },
|
||||||
|
m(m.route.Link, { class: "btn btn-outline-secondary btn-lg w-100", href: `/tag/${data.tag.id}/pages` }, 'Статьи с тегом'),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
result.push(
|
||||||
|
m('div', { class: 'row' },
|
||||||
|
m('div', { class: "col py-2" }, m.trust(data.tag.description)),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
result.push(breadcrumbs_render());
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
119
myapp/templates/public/domains/tag/tags.js
Normal file
119
myapp/templates/public/domains/tag/tags.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
function Tags() {
|
||||||
|
let data = {
|
||||||
|
filter: PanelFilter(),
|
||||||
|
raw_groups: {},
|
||||||
|
get groups() {
|
||||||
|
let result = {};
|
||||||
|
Object.keys(data.raw_groups).forEach(
|
||||||
|
function (group, groupIdx) {
|
||||||
|
let tags = data.raw_groups[group].filter(tag_filter);
|
||||||
|
if (tags.length > 0) {
|
||||||
|
result[group] = tags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
function breadcrumbs_render() {
|
||||||
|
let result = m('ul', { class: 'breadcrumb mt-2' }, [
|
||||||
|
m('li', { class: 'breadcrumb-item' }, m(m.route.Link, { href: '/' }, m('i', { class: 'fa fa-home' }))),
|
||||||
|
m('li', { class: 'breadcrumb-item active' }, 'Список тегов'),
|
||||||
|
]);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
function tag_filter(tag) {
|
||||||
|
let filter = data.filter.data;
|
||||||
|
let value = filter.value;
|
||||||
|
if (value.length < 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (tag.name.toLowerCase().includes(value.toLowerCase())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
function tags_get() {
|
||||||
|
m.request({
|
||||||
|
url: '/api',
|
||||||
|
method: "POST",
|
||||||
|
body: {
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": 'tags.groups',
|
||||||
|
"params": {
|
||||||
|
},
|
||||||
|
"id": get_id()
|
||||||
|
}
|
||||||
|
}).then(
|
||||||
|
function (response) {
|
||||||
|
if ('result' in response) {
|
||||||
|
data.raw_groups = response['result'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
oninit: function (vnode) {
|
||||||
|
console.log('Tags.oninit');
|
||||||
|
tags_get();
|
||||||
|
},
|
||||||
|
view: function (vnode) {
|
||||||
|
console.log('Tags.view');
|
||||||
|
result = [];
|
||||||
|
result.push(
|
||||||
|
breadcrumbs_render(),
|
||||||
|
m('div', { class: 'row' },
|
||||||
|
m('div', { class: "col h1 py-2" }, [
|
||||||
|
m('button', { type: "button", class: "btn btn-outline-secondary btn-lg me-2", onclick: function () { panel_show(data.filter.data) } },
|
||||||
|
m('i', { class: "fa fa-filter" })
|
||||||
|
),
|
||||||
|
'Облако тегов'
|
||||||
|
])
|
||||||
|
),
|
||||||
|
m('hr'),
|
||||||
|
);
|
||||||
|
result.push(m(data.filter));
|
||||||
|
if (Object.keys(data.groups).length > 0) {
|
||||||
|
let groups = [];
|
||||||
|
Object.keys(data.groups).forEach(
|
||||||
|
function (group, groupIdx) {
|
||||||
|
let odd = '';
|
||||||
|
if (groupIdx % 2) {
|
||||||
|
odd = 'btn-primary'
|
||||||
|
};
|
||||||
|
groups.push({ tag: '<', children: `<a href="#${groupIdx}" class="btn ${odd} btn-lg my-1 mx-1">${group}</a>` });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
result.push(
|
||||||
|
m('div', { class: 'row' },
|
||||||
|
m('div', { class: "col text-justify" }, [...groups])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
groups = [];
|
||||||
|
Object.keys(data.groups).forEach(
|
||||||
|
function (group, groupIdx) {
|
||||||
|
let odd = '';
|
||||||
|
if (groupIdx % 2) {
|
||||||
|
odd = ' bg-light'
|
||||||
|
};
|
||||||
|
let tags = data.groups[group].map(
|
||||||
|
function (tag, tagIdx) {
|
||||||
|
return m(m.route.Link, { class: "btn btn-outline-secondary font-monospace my-1 me-2", href: `/tag/${tag.id}` }, tag.name);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
groups.push(m('div', { class: 'row' }, [
|
||||||
|
m('div', { class: "col-md-1 py-2" + odd }, [
|
||||||
|
{ tag: '<', children: `<a id=${groupIdx} class="btn btn-outline-danger w-100 my-1">${group}</a>` },
|
||||||
|
// m(m.route.Link, {class: "text-decoration-none", href: "/tag/" + tag.id, title: "Тег #" + tag.id}, tag.name),
|
||||||
|
]),
|
||||||
|
m('div', { class: "col-md-11 py-2" + odd }, [...tags]),
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
);
|
||||||
|
result.push(...groups);
|
||||||
|
};
|
||||||
|
result.push(breadcrumbs_render());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
{% include 'header.html' %}
|
{% include 'header.html' %}
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<section id="app" class="container">
|
<section id="app" class="container">
|
||||||
|
|||||||
Reference in New Issue
Block a user