Merge remote-tracking branch 'silenceway/calibre-web/feature/allow-create-pages-d' into feature/custom-pages
commit
5d98b13bf2
@ -0,0 +1,108 @@
|
||||
import os
|
||||
import flask
|
||||
from flask import Blueprint, Flask, abort, request
|
||||
from functools import wraps
|
||||
from pathlib import Path
|
||||
from flask_login import current_user, login_required
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from .render_template import render_title_template
|
||||
from . import logger, config, ub
|
||||
from .constants import CONFIG_DIR as _CONFIG_DIR
|
||||
|
||||
log = logger.create()
|
||||
|
||||
editpage = Blueprint('editpage', __name__)
|
||||
|
||||
def edit_required(f):
|
||||
@wraps(f)
|
||||
def inner(*args, **kwargs):
|
||||
if current_user.role_edit() or current_user.role_admin():
|
||||
return f(*args, **kwargs)
|
||||
abort(403)
|
||||
|
||||
return inner
|
||||
|
||||
def _get_checkbox(dictionary, field, default):
|
||||
new_value = dictionary.get(field, default)
|
||||
convertor = lambda y: y == "on"
|
||||
new_value = convertor(new_value)
|
||||
|
||||
return new_value
|
||||
|
||||
@editpage.route("/admin/page/<string:file>", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@edit_required
|
||||
def edit_page(file):
|
||||
doc = ""
|
||||
title = ""
|
||||
name = ""
|
||||
icon = "file"
|
||||
is_enabled = True
|
||||
order = 0
|
||||
position = "0"
|
||||
|
||||
page = ub.session.query(ub.Page).filter(ub.Page.id == file).first()
|
||||
|
||||
try:
|
||||
title = page.title
|
||||
name = page.name
|
||||
icon = page.icon
|
||||
is_enabled = page.is_enabled
|
||||
order = page.order
|
||||
position = page.position
|
||||
except AttributeError:
|
||||
if file != "new":
|
||||
abort(404)
|
||||
|
||||
if request.method == "POST":
|
||||
to_save = request.form.to_dict()
|
||||
title = to_save.get("title", "").strip()
|
||||
name = to_save.get("name", "").strip()
|
||||
icon = to_save.get("icon", "").strip()
|
||||
position = to_save.get("position", "").strip()
|
||||
order = int(to_save.get("order", 0))
|
||||
content = to_save.get("content", "").strip()
|
||||
is_enabled = _get_checkbox(to_save, "is_enabled", True)
|
||||
|
||||
if page:
|
||||
page.title = title
|
||||
page.name = name
|
||||
page.icon = icon
|
||||
page.is_enabled = is_enabled
|
||||
page.order = order
|
||||
page.position = position
|
||||
ub.session_commit("Page edited {}".format(file))
|
||||
else:
|
||||
new_page = ub.Page(title=title, name=name, icon=icon, is_enabled=is_enabled, order=order, position=position)
|
||||
ub.session.add(new_page)
|
||||
ub.session_commit("Page added {}".format(file))
|
||||
|
||||
if (file == "new"):
|
||||
file = str(new_page.id)
|
||||
dir_config_path = os.path.join(_CONFIG_DIR, 'pages')
|
||||
file_name = Path(name + '.md')
|
||||
file_path = dir_config_path / file_name
|
||||
os.makedirs(dir_config_path, exist_ok=True)
|
||||
|
||||
try:
|
||||
with open(file_path, 'w') as f:
|
||||
f.write(content)
|
||||
f.close()
|
||||
except Exception as ex:
|
||||
log.error(ex)
|
||||
|
||||
if file != "new":
|
||||
try:
|
||||
dir_config_path = Path(_CONFIG_DIR) / 'pages'
|
||||
file_path = dir_config_path / f"{name}.md"
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
doc = f.read()
|
||||
except NotFound:
|
||||
log.error("'%s' was accessed but file doesn't exists." % file)
|
||||
|
||||
else:
|
||||
doc = "## New file\n\nInformation"
|
||||
|
||||
return render_title_template("edit_page.html", title=title, name=name, icon=icon, is_enabled=is_enabled, order=order, position=position, content=doc, file=file)
|
@ -0,0 +1,28 @@
|
||||
import flask
|
||||
import json
|
||||
from flask import Blueprint, jsonify, make_response,abort
|
||||
from flask_login import current_user, login_required
|
||||
from functools import wraps
|
||||
from flask_babel import gettext as _
|
||||
|
||||
from .render_template import render_title_template
|
||||
from . import ub, db
|
||||
|
||||
listpages = Blueprint('listpages', __name__)
|
||||
|
||||
def edit_required(f):
|
||||
@wraps(f)
|
||||
def inner(*args, **kwargs):
|
||||
if current_user.role_edit() or current_user.role_admin():
|
||||
return f(*args, **kwargs)
|
||||
abort(403)
|
||||
|
||||
return inner
|
||||
|
||||
@listpages.route("/admin/pages/", methods=["GET"])
|
||||
@login_required
|
||||
@edit_required
|
||||
def show_list():
|
||||
pages = ub.session.query(ub.Page).order_by(ub.Page.position).order_by(ub.Page.order).all()
|
||||
|
||||
return render_title_template('list_pages.html', title=_("Pages List"), page="book_table", pages=pages)
|
@ -0,0 +1,38 @@
|
||||
import os
|
||||
import flask
|
||||
import markdown
|
||||
from flask import abort
|
||||
from pathlib import Path
|
||||
from flask_babel import gettext as _
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from . import logger, config, ub
|
||||
from .render_template import render_title_template
|
||||
from .constants import CONFIG_DIR as _CONFIG_DIR
|
||||
|
||||
page = flask.Blueprint('page', __name__)
|
||||
|
||||
log = logger.create()
|
||||
|
||||
@page.route('/page/<string:file>', methods=['GET'])
|
||||
def get_page(file):
|
||||
page = ub.session.query(ub.Page)\
|
||||
.filter(ub.Page.name == file)\
|
||||
.filter(ub.Page.is_enabled)\
|
||||
.first()
|
||||
|
||||
if not page:
|
||||
log.error(f"'{file}' was accessed but is not enabled or it's not in database.")
|
||||
abort(404)
|
||||
|
||||
try:
|
||||
dir_config_path = Path(_CONFIG_DIR) / 'pages'
|
||||
file_path = dir_config_path / f"{file}.md"
|
||||
with open(file_path, 'r') as f:
|
||||
temp_md = f.read()
|
||||
body = markdown.markdown(temp_md)
|
||||
|
||||
return render_title_template('page.html', body=body, title=page.title, page=page.name)
|
||||
except NotFound:
|
||||
log.error("'%s' was accessed but file doesn't exists." % file)
|
||||
abort(404)
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.sk={days:["Nedeľa","Pondelok","Utorok","Streda","Štvrtok","Piatok","Sobota"],daysShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob"],daysMin:["Ne","Po","Ut","St","Št","Pia","So"],months:["Január","Február","Marec","Apríl","Máj","Jún","Júl","August","September","Október","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],today:"Dnes",clear:"Vymazať",weekStart:1,format:"d.m.yyyy"}}(jQuery);
|
@ -0,0 +1,45 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div class="discover">
|
||||
<div><a class="session" href="{{url_for('listpages.show_list')}}">{{_('Back')}}</a></div>
|
||||
<h2>{{_('Edit page')}}</h2>
|
||||
<form role="form" class="col-md-10 col-lg-6" method="POST" action="{{ url_for('editpage.edit_page', file=file) }}"
|
||||
autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<div class="form-group">
|
||||
<label for="title">{{_('Title')}}</label>
|
||||
<input type="text" class="form-control" name="title" id="title" value="{{ title }}" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name">{{_('Name')}}</label>
|
||||
<input type="text" class="form-control" name="name" id="name" value="{{ name }}" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="icon">{{_('Icon')}}</label>
|
||||
<input type="text" class="form-control" name="icon" id="icon" value="{{ icon }}" required>
|
||||
<a href="https://www.w3schools.com/bootstrap/bootstrap_ref_comp_glyphs.asp" target="_blank" rel="noopener">{{_('Icons list')}}</a>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="content">{{_('Content')}}</label>
|
||||
<textarea class="form-control" name="content" id="content" rows="15">{{ content }}</textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="position">{{_('Position')}}</label>
|
||||
<select name="position" id="position" class="form-control">
|
||||
<option value="0" {% if position=="0" %}selected{% endif %}>{{ _("Sidebar Bottom") }}</option>
|
||||
<option value="1" {% if position=="1" %}selected{% endif %}>{{ _("Sidebar Top") }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" id="is_enabled" name="is_enabled" {% if is_enabled %}checked{% endif %}>
|
||||
<label for="is_enabled">{{_('Enabled')}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="order">{{_('Order')}}</label>
|
||||
<input type="number" class="form-control" name="order" id="order" value="{{ order }}" required>
|
||||
</div>
|
||||
<button type="submit" name="submit" id="page_submit" class="btn btn-default">{{_('Save')}}</button>
|
||||
<a href="{{ url_for('admin.admin') }}" id="config_back" class="btn btn-default">{{_('Cancel')}}</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,52 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block header %}
|
||||
<link href="{{ url_for('static', filename='css/libs/bootstrap-table.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/libs/bootstrap-editable.css') }}" rel="stylesheet">
|
||||
<link href="{{ url_for('static', filename='css/libs/bootstrap-select.min.css') }}" rel="stylesheet" >
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<h2 class="{{page}}">{{_(title)}}</h2>
|
||||
<table class="table table-striped" id="table_user">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{_('Name')}}</th>
|
||||
<th>{{_('Title')}}</th>
|
||||
<th>{{_('Icon')}}</th>
|
||||
<th>{{_('Position')}}</th>
|
||||
<th>{{_('Enabled')}}</th>
|
||||
<th>{{_('Order')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for page in pages %}
|
||||
<tr>
|
||||
<td><a class="session" href="{{url_for('editpage.edit_page', file=page.id)}}">{{page.name}}</a></td>
|
||||
<td>{{page.title}}</td>
|
||||
<td>{{page.icon}}</td>
|
||||
<td>{{_('bottom') if page.position == "0" else _('top')}}</td>
|
||||
<td>
|
||||
{% if page.is_enabled %}
|
||||
<span class="glyphicon glyphicon-ok"></span>
|
||||
{% else %}
|
||||
<span class="glyphicon glyphicon-remove"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{page.order}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<a class="session" href="{{url_for('editpage.edit_page', file="new")}}">{{_('New Page')}}</a>
|
||||
{% endblock %}
|
||||
{% block js %}
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table-locale-all.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table-editable.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-editable.min.js') }}"></script>
|
||||
{% if not current_user.locale == 'en' %}
|
||||
<script
|
||||
src="{{ url_for('static', filename='js/libs/bootstrap-table/locale/bootstrap-table-' + current_user.locale + '.min.js') }}"
|
||||
charset="UTF-8"></script>
|
||||
{% endif %}
|
||||
<script src="{{ url_for('static', filename='js/table.js') }}"></script>
|
||||
{% endblock %}
|
@ -0,0 +1,4 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<div>{{body|safe}}</div>
|
||||
{% endblock %}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,19 +1,20 @@
|
||||
Werkzeug<3.0.0
|
||||
APScheduler>=3.6.3,<3.11.0
|
||||
Babel>=1.3,<3.0
|
||||
Flask-Babel>=0.11.1,<3.1.0
|
||||
Flask-Babel>=0.11.1,<4.1.0
|
||||
Flask-Login>=0.3.2,<0.6.3
|
||||
Flask-Principal>=0.3.2,<0.5.1
|
||||
Flask>=1.0.2,<2.4.0
|
||||
iso-639>=0.4.5,<0.5.0
|
||||
PyPDF>=3.0.0,<3.8.0
|
||||
PyPDF>=3.0.0,<3.16.0
|
||||
pytz>=2016.10
|
||||
requests>=2.11.1,<2.29.0
|
||||
SQLAlchemy>=1.3.0,<2.0.0
|
||||
tornado>=4.1,<6.3
|
||||
requests>=2.28.0,<2.32.0
|
||||
SQLAlchemy>=1.3.0,<2.1.0
|
||||
tornado>=6.3,<6.4
|
||||
Wand>=0.4.4,<0.7.0
|
||||
unidecode>=0.04.19,<1.4.0
|
||||
lxml>=3.8.0,<5.0.0
|
||||
flask-wtf>=0.14.2,<1.2.0
|
||||
flask-wtf>=0.14.2,<1.3.0
|
||||
chardet>=3.0.0,<4.1.0
|
||||
advocate>=1.0.0,<1.1.0
|
||||
Flask-Limiter>=2.3.0,<3.4.0
|
||||
Flask-Limiter>=2.3.0,<3.6.0
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue