Merge pull request 'dark_theme' (#1) from dark_theme into master

Reviewed-on: #1
This commit is contained in:
absurdo 2023-11-26 20:26:36 +00:00
commit 7f2a54314b
5 changed files with 405 additions and 9 deletions

View file

@ -25,7 +25,9 @@ def ausers():
user_admin.fields['last_login'].name_form=HiddenForm
user_admin.create_forms(['username', 'password', 'email', 'privileges', 'lang', 'disabled', 'double_auth', 'last_login'])
user_admin.fields['dark_theme'].name_form=SelectForm
user_admin.create_forms(['username', 'password', 'email', 'privileges', 'lang', 'dark_theme', 'disabled', 'double_auth', 'last_login'])
user_admin.forms['privileges'].arr_select={0: I18n.lang('admin', 'without_privileges', 'Without privileges'), 1: I18n.lang('admin', 'selected_privileges', 'Selected privileges'), 2: I18n.lang('admin', 'administrator', 'Administrator')}
@ -35,6 +37,8 @@ def ausers():
user_admin.fields['password'].protected=False
user_admin.forms['dark_theme'].arr_select={0: I18n.lang('admin', 'light_theme', 'Light theme'), 1: I18n.lang('admin', 'dark_theme', 'Dark theme')}
user_admin.check_user=False
user_admin.check_email=False
@ -46,7 +50,7 @@ def ausers():
admin.list.search_fields=['username']
admin.arr_fields_edit=['username', 'password', 'repeat_password', 'email', 'lang', 'double_auth', 'disabled', 'last_login']
admin.arr_fields_edit=['username', 'password', 'repeat_password', 'email', 'lang', 'dark_theme', 'double_auth', 'disabled', 'last_login']
form_admin=admin.show()

View file

@ -115,6 +115,7 @@ for app_load in config_admin:
@admin_app.route('/admin/')
def admin():
return t.load_template('home.phtml', title=I18n.lang('admin', 'admin', 'Admin'))
"""
@ -251,7 +252,11 @@ def login():
sendmail.send(config.portal_email, [arr_user['email']], I18n.lang('admin', 'code_for_complete_login', 'Code for complete login'), I18n.lang('admin', 'code_for_complete_login_explain', 'We send to you a code for activate your account using double authentication:')+"\n"+token_auth, content_type='plain', attachments=[])
if arr_user['dark_theme']:
session['theme']='1'
else:
session['theme']='0'
arr_update['last_login']=now()
if len(arr_update)>0:
@ -394,6 +399,17 @@ def auth_check():
return {'error': error, 'you_cannot_login': you_cannot_login}
@admin_app.route('/admin/change_theme/')
def change_theme():
theme_selected=str(request.args.get('theme', '0'))
session['theme']=theme_selected
error=0
return {'error': error}
"""
@admin_app.route('/admin/recovery_password/')
def recovery_password():

View file

@ -1,4 +1,11 @@
/** {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}*/
body
{
@ -6,23 +13,42 @@ body
background-color:#f4f6f9;
font-family: "Roboto", sans, sans-serif, serif;
font-size: 16px;
/*-webkit-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
-webkit-transition-property: background-color, color;
transition-property: background-color, color;*/
}
a
{
body.dark {
background-color: #232834;
color: #fbfbfb;
/*-webkit-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
-webkit-transition-property: background-color, color;
transition-property: background-color, color;*/
}
a {
color: #1c6280;
}
a:hover
{
a:hover {
color: #d54e21;
}
.dark a {
color: #5fa6c4;
}
#header
{
@ -39,6 +65,14 @@ a:hover
}
.dark #header {
background-color:#1e1412;
}
#title_phango
{
font-size:28px;
@ -99,6 +133,20 @@ h1 {
}
.dark h1 {
background-color:#000a22;
color: #fbfbfb;
border-color: #000;
}
.dark h2 {
color: #fbfbfb;
}
p {
border: solid #cbcbcb;
@ -142,6 +190,16 @@ p {
box-sizing: border-box;
/* padding-bottom: 100px;*/
overflow:hidden;
height:100%;
-webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75);
box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.75);
}
.dark #menu {
}
#menu a
@ -257,8 +315,23 @@ p {
border: solid #cbcbcb;
border-width: 0px 0px 1px 0px;
min-height: 90vh;
/*-webkit-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;*/
}
.dark .content_admin {
background-color: #1e202a;
/*-webkit-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;*/
border: solid #323232;
border-width: 0px 0px 1px 0px;
}
.content_admin i {
margin-right: 10px;
@ -271,8 +344,10 @@ p {
width:82%;
padding:0px 0px 0px 0px;
box-sizing: border-box;
}
.content
{
padding:0px 10px 5px 10px;
@ -320,6 +395,13 @@ p {
}
.dark .form {
background-color: #1e202a;
border-color: #323232;
}
.form textarea {
width:100%;
@ -408,6 +490,12 @@ table {
}
.dark .table_list {
border: solid #323232 1px;
}
.title_list td, .fields_span_title {
margin:0px;
@ -423,6 +511,13 @@ table {
}
.dark .title_list td {
background-color:#000a22;
}
.fields_span_title, div.options_td , div.fields_span_table_data {
box-sizing: border-box;
@ -449,6 +544,13 @@ table {
}
.dark .row_list td {
background-color: #2d313b;
color: #fbfbfb;
}
div.fields_span_table_data {
box-sizing: border-box;
@ -472,6 +574,13 @@ div.fields_span_table_data {
}
.dark .cont_text, .dark .cont {
background-color: #2d313b;
border-color: #343434;
}
.cont_top {
border-width: 1px 1px 1px 1px;
@ -518,6 +627,12 @@ div.fields_span_table_data {
}
.dark .error {
color: #ff3232;
}
.hidden_form
{
@ -577,9 +692,11 @@ a:hover.no_choose_flag
#center_body input {
border: solid #bcbcbc;
border-width:1px;
border-width:2px;
border-radius:5px;
background: #eeeeee;
padding: 2px 4px;
font-size:16px;
}
@ -589,6 +706,13 @@ a:hover.no_choose_flag
}
.dark #center_body input {
background-color: #2d313b;
color: #fbfbfb;
}
#center_body input[type="submit"], #center_body input[type="button"], #center_body input[type="button"].button_blue
{
@ -611,6 +735,12 @@ a:hover.no_choose_flag
}
.dark #center_body input[type="button"] {
background: #d08b2c;
}
#center_body input:hover[type="submit"], #center_body input[type="button"].button_blue
{
@ -627,6 +757,15 @@ a:hover.no_choose_flag
}
#center_body input:hover[type="button"].button_blue
{
background: #215181;
cursor: pointer;
}
#center_body input[type="text"], #center_body input[type="password"]
{
@ -647,6 +786,16 @@ a:hover.no_choose_flag
border: solid #bcbcbc;
border-width:1px;
border-radius:5px;
padding: 2px 5px;
border: solid #cbcbcb 2px;
font-size: 16px;
}
.dark #center_body select {
background-color: #2d313b;
color: #fbfbfb;
}
@ -969,6 +1118,14 @@ h2.title_container {
}
.dark h2.title_container {
background-color: #2d313b;
border-color: #343434;
color: #fbfbfb;
}
.container_warning h2.title_container {
background:#dc3545;
@ -1001,6 +1158,144 @@ h2.title_container {
}
.dark .container_content {
background-color: #2d313b;
border-color: #343434;
color: #fbfbfb;
}
/* Switch for dark mode */
/* switches css */
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 40px;
height: 16px;
}
/* Hide default HTML checkbox */
.switch input {display:none;}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
height: 16px;
width:38px;
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;
}
/* before is the checkbox */
.slider:before {
position: absolute;
content: "";
height: 22px;
width: 22px;
left: -1px;
top: -3px;
background-color: #fbfbfb;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #447211;
}
input:focus + .slider {
box-shadow: 0 0 1px #447211;
}
input:checked + .slider:before {
-webkit-transform: translateX(21px);
-ms-transform: translateX(21px);
transform: translateX(21px);
background-color: #7ed321;
}
input:checked + .slider_grey {
background-color: #ccc;
}
input:focus + .slider_grey {
box-shadow: 0 0 1px #ccc;
}
input:checked + .slider_grey:before {
-webkit-transform: translateX(21px);
-ms-transform: translateX(21px);
transform: translateX(21px);
background-color: #fbfbfb;
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.container_switch {
margin-top:6px;
display:inline-block;
float:right;
}
.switch-btn {
position:absolute;
/*border: solid #f00 1px;*/
right:4px;
top:8px;
z-index:9999;
}
.switch-slider {
text-align:center;
display: inline-block;
}
.switch-text {
display: inline-block;
font-size: 12px;
position:relative;
top: -4px;
left:-2px;
color: #000;
}
.dark .switch-text {
color: #fbfbfb;
}
/* Media queries */

View file

@ -94,6 +94,8 @@ class UserAdmin(UserModel):
self.register(corefields.BooleanField('double_auth'))
self.register(corefields.BooleanField('dark_theme'))
#self.register(corefields.IntegerField('num_tries', 1))
self.register(DateTimeField('last_login'))

View file

@ -1,3 +1,16 @@
<%
from flask import session
dark_checked=''
dark_css=''
if session.get('theme', '0')=='1':
dark_checked='checked'
dark_css='dark'
%>
<!DOCTYPE html>
<html>
<head>
@ -20,7 +33,7 @@ ${load_js()|n}
<%block name="extra_header">
</%block>
</head>
<body>
<body class="${dark_css}">
<div id="layer_loading" style="display:none;"><div id="container_loading"><div class="lds-dual-ring"></div></div></div>
<div id="languages_general">
</div>
@ -44,8 +57,10 @@ ${load_js()|n}
%>
<span id="title_phango">${portal_admin_name_set[0]}</span> <span id="title_framework">${portal_admin_name_set[1]}</span>
</%block>
</div>
<div class="content_admin">
<nav id="menu" class="nav-collapse">
<ul>
<li class="menu_title"><%block name="applications"><i class="fa fa-gear" aria-hidden="true"></i>${lang('admin', 'applications', 'Applications')}</li></%block>
@ -90,6 +105,17 @@ ${load_js()|n}
</nav>
<div class="contents">
<h1>${title}</h1>
<div class="switch-btn">
<div class="switch-text">
Dark Mode
</div>
<div class="switch-slider">
<label class="switch">
<input type="checkbox" name="theme" value="1" id="theme" ${dark_checked}/>
<span class="slider round"></span>
</label>
</div>
</div>
<div class="content">
<%
from flask import get_flashed_messages
@ -117,6 +143,59 @@ ${load_js()|n}
trigger: 'click'
});
const slider = document.querySelector('input[name="theme"]');
slider.addEventListener("change", function () {
//Block button while send to ajax.
$(this).prop("disabled",true);
var dark='';
if (this.checked) {
document.body.classList.add("dark");
dark='1';
} else {
document.body.classList.remove("dark");
dark='0';
}
$.ajax({
url: "${url_for('admin_app.change_theme')}?theme="+dark,
type: 'GET',
data: {},
success: function (data) {
if(!data.error) {
console.log('Changed to dark in all pages');
}
else {
console.log('Cannot set dark theme in all pages!');
}
$(slider).prop("disabled",false);
},
error: function (data) {
alert('Error: '+data.status+' '+data.statusText);
$(slider).prop("disabled", false);
},
dataType: 'json'
});
});
</script>
<%block name="jscript_block">
</%block>