feat(admin): added legal pages
parent
5e4cb0fc6c
commit
fe949b9f33
|
@ -0,0 +1,82 @@
|
|||
import logging as log
|
||||
import os
|
||||
from pprint import pprint
|
||||
|
||||
from minio import Minio
|
||||
from minio.commonconfig import REPLACE, CopySource
|
||||
from minio.deleteobjects import DeleteObject
|
||||
from requests import get, post
|
||||
|
||||
from admin import app
|
||||
|
||||
|
||||
class Avatars:
|
||||
def __init__(self):
|
||||
self.mclient = Minio(
|
||||
"isard-sso-avatars:9000",
|
||||
access_key="AKIAIOSFODNN7EXAMPLE",
|
||||
secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
||||
secure=False,
|
||||
)
|
||||
self.bucket = "master-avatars"
|
||||
self._minio_set_realm()
|
||||
# self.update_missing_avatars()
|
||||
|
||||
def add_user_default_avatar(self, userid, role="unknown"):
|
||||
self.mclient.fput_object(
|
||||
self.bucket,
|
||||
userid,
|
||||
os.path.join(app.root_path, "../custom/avatars/" + role + ".jpg"),
|
||||
content_type="image/jpeg ",
|
||||
)
|
||||
log.warning(
|
||||
" AVATARS: Updated avatar for user " + userid + " with role " + role
|
||||
)
|
||||
|
||||
def delete_user_avatar(self, userid):
|
||||
self.minio_delete_object(userid)
|
||||
|
||||
def update_missing_avatars(self, users):
|
||||
sys_roles = ["admin", "manager", "teacher", "student"]
|
||||
for u in self.get_users_without_image(users):
|
||||
try:
|
||||
img = [r + ".jpg" for r in sys_roles if r in u["roles"]][0]
|
||||
except:
|
||||
img = "unknown.jpg"
|
||||
|
||||
self.mclient.fput_object(
|
||||
self.bucket,
|
||||
u["id"],
|
||||
os.path.join(app.root_path, "../custom/avatars/" + img),
|
||||
content_type="image/jpeg ",
|
||||
)
|
||||
log.warning(
|
||||
" AVATARS: Updated avatar for user "
|
||||
+ u["username"]
|
||||
+ " with role "
|
||||
+ img.split(".")[0]
|
||||
)
|
||||
|
||||
def _minio_set_realm(self):
|
||||
if not self.mclient.bucket_exists(self.bucket):
|
||||
self.mclient.make_bucket(self.bucket)
|
||||
|
||||
def minio_get_objects(self):
|
||||
return [o.object_name for o in self.mclient.list_objects(self.bucket)]
|
||||
|
||||
def minio_delete_all_objects(self):
|
||||
delete_object_list = map(
|
||||
lambda x: DeleteObject(x.object_name),
|
||||
self.mclient.list_objects(self.bucket),
|
||||
)
|
||||
errors = self.mclient.remove_objects(self.bucket, delete_object_list)
|
||||
for error in errors:
|
||||
log.error(" AVATARS: Error occured when deleting avatar object: " + error)
|
||||
|
||||
def minio_delete_object(self, oid):
|
||||
errors = self.mclient.remove_objects(self.bucket, [DeleteObject(oid)])
|
||||
for error in errors:
|
||||
log.error(" AVATARS: Error occured when deleting avatar object: " + error)
|
||||
|
||||
def get_users_without_image(self, users):
|
||||
return [u for u in users if u["id"] and u["id"] not in self.minio_get_objects()]
|
|
@ -0,0 +1,89 @@
|
|||
$(document).ready(function () {
|
||||
init_wysiwyg();
|
||||
|
||||
var lang = getCookie('KEYCLOAK_LOCALE') ? getCookie('KEYCLOAK_LOCALE') : 'ca'
|
||||
$('#legal-lang').val(lang)
|
||||
getLangLegal(lang)
|
||||
// $('#privacy-lang').val(lang)
|
||||
|
||||
// $.ajax({
|
||||
// type: "GET",
|
||||
// url: "/api/legal/privacy",
|
||||
// data: {
|
||||
// lang: lang
|
||||
// },
|
||||
// success: function (data) {
|
||||
// $('#editor-privacy').html(data.html)
|
||||
// }
|
||||
// })
|
||||
|
||||
$("#save-legal").click(function () {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/api/legal/legal",
|
||||
data: {
|
||||
'html': $('#editor-legal').cleanHtml(),
|
||||
'lang': $('#legal-lang').val()
|
||||
},
|
||||
success: function () {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
$('#legal-lang').on('change', function() {
|
||||
getLangLegal(this.value)
|
||||
});
|
||||
|
||||
// $("#save-privacy").click(function () {
|
||||
// $.ajax({
|
||||
// type: "POST",
|
||||
// url: "/api/legal/privacy",
|
||||
// data: {
|
||||
// 'html': $('#editor-privacy').cleanHtml(),
|
||||
// 'lang': $('#legal-lang').val()
|
||||
// },
|
||||
// success: function () {
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
||||
function getLangLegal(lang) {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/api/legal/legal",
|
||||
data: {
|
||||
lang: lang
|
||||
},
|
||||
success: function (data) {
|
||||
$('#editor-legal').html(data.html)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getCookie(cname) {
|
||||
let name = cname + "=";
|
||||
let decodedCookie = decodeURIComponent(document.cookie);
|
||||
let ca = decodedCookie.split(';');
|
||||
for(let i = 0; i <ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == ' ') {
|
||||
c = c.substring(1);
|
||||
}
|
||||
if (c.indexOf(name) == 0) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function init_wysiwyg() {
|
||||
$("#editor-legal").wysiwyg({
|
||||
toolbarSelector: '[data-target="#editor-legal"]'
|
||||
});
|
||||
// $("#editor-privacy").wysiwyg({
|
||||
// toolbarSelector: '[data-target="#editor-privacy"]'
|
||||
// });
|
||||
window.prettyPrint;
|
||||
prettyPrint();
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<div class="form-group row">
|
||||
<div id="alerts"></div>
|
||||
<div
|
||||
class="btn-toolbar editor"
|
||||
data-role="editor-toolbar_{{ type }}"
|
||||
data-target="#editor-{{ type }}"
|
||||
>
|
||||
|
||||
<div class="col-md-1 col-sm-1 ">
|
||||
<select id="{{type}}-lang" class="form-control">
|
||||
{% for lang in [{'text': 'Español', 'code': 'es'}, {'text': 'English', 'code': 'en'}, {'text': 'Català', 'code': 'ca'}, {'text': 'Français', 'code': 'fr'}] %}
|
||||
<option value="{{ lang['code'] }}">{{ lang['text'] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn dropdown-toggle" data-toggle="dropdown" title="Font Size"
|
||||
><i class="fa fa-text-height"></i> <b class="caret"></b
|
||||
></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<a data-edit="fontSize 5">
|
||||
<p style="font-size: 17px">Huge</p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-edit="fontSize 3">
|
||||
<p style="font-size: 14px">Normal</p>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a data-edit="fontSize 1">
|
||||
<p style="font-size: 11px">Small</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn" data-edit="bold" title="Bold (Ctrl/Cmd+B)"
|
||||
><i class="fa fa-bold"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="italic" title="Italic (Ctrl/Cmd+I)"
|
||||
><i class="fa fa-italic"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="strikethrough" title="Strikethrough"
|
||||
><i class="fa fa-strikethrough"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="underline" title="Underline (Ctrl/Cmd+U)"
|
||||
><i class="fa fa-underline"></i
|
||||
></a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn" data-edit="insertunorderedlist" title="Bullet list"
|
||||
><i class="fa fa-list-ul"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="insertorderedlist" title="Number list"
|
||||
><i class="fa fa-list-ol"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="outdent" title="Reduce indent (Shift+Tab)"
|
||||
><i class="fa fa-dedent"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="indent" title="Indent (Tab)"
|
||||
><i class="fa fa-indent"></i
|
||||
></a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn" data-edit="justifyleft" title="Align Left (Ctrl/Cmd+L)"
|
||||
><i class="fa fa-align-left"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="justifycenter" title="Center (Ctrl/Cmd+E)"
|
||||
><i class="fa fa-align-center"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="justifyright" title="Align Right (Ctrl/Cmd+R)"
|
||||
><i class="fa fa-align-right"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="justifyfull" title="Justify (Ctrl/Cmd+J)"
|
||||
><i class="fa fa-align-justify"></i
|
||||
></a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group">
|
||||
<a class="btn" data-edit="undo" title="Undo (Ctrl/Cmd+Z)"
|
||||
><i class="fa fa-undo"></i
|
||||
></a>
|
||||
<a class="btn" data-edit="redo" title="Redo (Ctrl/Cmd+Y)"
|
||||
><i class="fa fa-repeat"></i
|
||||
></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="editor-{{ type }}" type="{{ type }}" class="editor-wrapper"></div>
|
||||
|
||||
<textarea name="descr" id="descr" style="display: none"></textarea>
|
||||
</div>
|
|
@ -0,0 +1,81 @@
|
|||
<!-- extend base layout -->
|
||||
{% extends "base.html" %} {% block css %}
|
||||
<!-- Ion.RangeSlider -->
|
||||
<link href="/vendors/normalize-css/normalize.css" rel="stylesheet" />
|
||||
<!-- Switchery -->
|
||||
<link href="/vendors/switchery/dist/switchery.min.css" rel="stylesheet" />
|
||||
<!-- Bootstrap Colorpicker -->
|
||||
<link
|
||||
href="/vendors/mjolnic-bootstrap-colorpicker/dist/css/bootstrap-colorpicker.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
{% endblock %} {% block content %}
|
||||
|
||||
<style>
|
||||
#select_fa {
|
||||
font-family: "FontAwesome", "Liberation Sans";
|
||||
font-size: 14px;
|
||||
}
|
||||
#select_fa::before {
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
<div class="row">
|
||||
<!-- form color picker -->
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<div class="x_panel">
|
||||
<div class="x_title">
|
||||
<h2>Legal<small>Company/School</small></h2>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="x_content">
|
||||
{% with type = 'legal' %}
|
||||
{% include 'aux/text-editor.html' %}
|
||||
{% endwith %}
|
||||
<div class="form-group row docs-buttons">
|
||||
<ul class="nav navbar-right panel_toolbox">
|
||||
<li>
|
||||
<button id="save-legal" type="button" class="btn btn-primary">
|
||||
Save changes
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="row">
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<div class="x_panel">
|
||||
<div class="x_title">
|
||||
<h2>Privacy policy<small></small></h2>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
<div class="x_content">
|
||||
{% with type = 'privacy' %}
|
||||
{% include 'aux/text-editor.html' %}
|
||||
{% endwith %}
|
||||
<div class="form-group row docs-buttons">
|
||||
<ul class="nav navbar-right panel_toolbox">
|
||||
<li>
|
||||
<button id="save-privacy" type="button" class="btn btn-primary">
|
||||
Save changes
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
{% endblock %} {% block pagescript %}
|
||||
<script src="/static/js/legal.js"></script>
|
||||
<!-- bootstrap-wysiwyg -->
|
||||
<script src="/vendors/bootstrap-wysiwyg/js/bootstrap-wysiwyg.min.js"></script>
|
||||
<script src="/vendors/jquery.hotkeys/jquery.hotkeys.js"></script>
|
||||
<script src="/vendors/google-code-prettify/src/prettify.js"></script>
|
||||
{% endblock %}
|
||||
</div>
|
|
@ -509,3 +509,32 @@ def dashboard_put(item):
|
|||
500,
|
||||
{"Content-Type": "application/json"},
|
||||
)
|
||||
|
||||
@app.route("/api/legal/<item>", methods=["GET", "POST"])
|
||||
# @login_required
|
||||
def legal_put(item):
|
||||
if request.method == "GET":
|
||||
if item == "legal":
|
||||
lang = request.args.get("lang")
|
||||
return json.dumps({ "html": "<b>Legal</b><br>This works! in lang: "+lang}), 200, {'Content-Type': 'application/json'}
|
||||
# if item == "privacy":
|
||||
# return json.dumps({ "html": "<b>Privacy policy</b><br>This works!"}), 200, {'Content-Type': 'application/json'}
|
||||
if request.method == "POST":
|
||||
if item == "legal":
|
||||
data = None
|
||||
try:
|
||||
data = request.json
|
||||
html = data["html"]
|
||||
lang = data["lang"]
|
||||
except:
|
||||
log.error(traceback.format_exc())
|
||||
return json.dumps(data), 200, {'Content-Type': 'application/json'}
|
||||
# if item == "privacy":
|
||||
# data = None
|
||||
# try:
|
||||
# data = request.json
|
||||
# html = data["html"]
|
||||
# lang = data["lang"]
|
||||
# except:
|
||||
# log.error(traceback.format_exc())
|
||||
# return json.dumps(data), 200, {'Content-Type': 'application/json'}
|
||||
|
|
|
@ -86,13 +86,19 @@ def avatar(userid):
|
|||
|
||||
|
||||
@app.route("/dashboard")
|
||||
# @login_required
|
||||
@login_required
|
||||
def dashboard(provider=False):
|
||||
data = json.loads(requests.get("http://isard-sso-api/json").text)
|
||||
return render_template(
|
||||
"pages/dashboard.html", title="Customization", nav="Customization", data=data
|
||||
)
|
||||
|
||||
@app.route("/legal")
|
||||
@login_required
|
||||
def legal():
|
||||
# data = json.loads(requests.get("http://isard-sso-api/json").text)
|
||||
return render_template("pages/legal.html", title="Legal", nav="Legal", data={})
|
||||
|
||||
|
||||
### SYS ADMIN
|
||||
|
||||
|
|
Loading…
Reference in New Issue