From b59974c0e4dfb1537ad27257234db463873d7332 Mon Sep 17 00:00:00 2001 From: Ross Mountjoy Date: Sat, 1 Feb 2020 11:55:14 -0500 Subject: [PATCH] user edit, fixed app heights, added api tutorial ready for docker --- dashmachine/main/routes.py | 2 +- dashmachine/main/utils.py | 1 + dashmachine/settings_system/routes.py | 18 +++ dashmachine/static/css/global/style.css | 4 + dashmachine/static/js/global/dashmachine.js | 8 + dashmachine/static/js/main/home.js | 30 ++++ .../static/js/settings_system/settings.js | 25 ++- dashmachine/templates/main/home.html | 55 ++----- .../templates/settings_system/settings.html | 153 ++++++++++++++---- dashmachine/user_system/forms.py | 6 +- dashmachine/user_system/utils.py | 5 +- 11 files changed, 229 insertions(+), 78 deletions(-) create mode 100644 dashmachine/static/js/main/home.js diff --git a/dashmachine/main/routes.py b/dashmachine/main/routes.py index 19a3c40..32a3952 100755 --- a/dashmachine/main/routes.py +++ b/dashmachine/main/routes.py @@ -63,7 +63,7 @@ def app_view(url): @main.route("/load_rest_data", methods=["GET"]) def load_rest_data(): data_template = get_rest_data(request.args.get("template")) - return data_template[:50] + return data_template # ------------------------------------------------------------------------------ diff --git a/dashmachine/main/utils.py b/dashmachine/main/utils.py index b73f48b..80a64f8 100755 --- a/dashmachine/main/utils.py +++ b/dashmachine/main/utils.py @@ -164,6 +164,7 @@ def public_route(decorated_function): def dashmachine_init(): + read_config() read_template_apps() user_data_folder = os.path.join(dashmachine_folder, "user_data") diff --git a/dashmachine/settings_system/routes.py b/dashmachine/settings_system/routes.py index 9c11567..1b60560 100644 --- a/dashmachine/settings_system/routes.py +++ b/dashmachine/settings_system/routes.py @@ -2,6 +2,7 @@ import os from flask import render_template, request, Blueprint, jsonify from dashmachine.settings_system.forms import ConfigForm from dashmachine.user_system.forms import UserForm +from dashmachine.user_system.utils import add_edit_user from dashmachine.main.utils import read_config, row2dict from dashmachine.main.models import Files, TemplateApps from dashmachine.paths import backgrounds_images_folder, icons_images_folder @@ -73,3 +74,20 @@ def update(): @settings_system.route("/settings/check_update", methods=["GET"]) def check_update(): return str(check_needed()) + + +@settings_system.route("/settings/edit_user", methods=["POST"]) +def edit_user(): + form = UserForm() + if form.validate_on_submit(): + if form.password.data != form.confirm_password.data: + return jsonify(data={"err": "Passwords don't match"}) + add_edit_user(form.username.data, form.password.data) + else: + err_str = "" + for fieldName, errorMessages in form.errors.items(): + err_str += f"{fieldName}: " + for err in errorMessages: + err_str += f"{err} " + return jsonify(data={"err": err_str}) + return jsonify(data={"err": "success"}) diff --git a/dashmachine/static/css/global/style.css b/dashmachine/static/css/global/style.css index ea92c7e..78227b2 100644 --- a/dashmachine/static/css/global/style.css +++ b/dashmachine/static/css/global/style.css @@ -25,6 +25,10 @@ body } } +.code { + font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; +} + #main { padding-left: 0; diff --git a/dashmachine/static/js/global/dashmachine.js b/dashmachine/static/js/global/dashmachine.js index 11afe71..0349fab 100644 --- a/dashmachine/static/js/global/dashmachine.js +++ b/dashmachine/static/js/global/dashmachine.js @@ -74,10 +74,18 @@ function show_sidenav(){ localStorage.setItem('sidenav_hidden', null); } +function apply_settings(settings_theme, settings_accent){ + localStorage.setItem('mode', settings_theme); + document.documentElement.setAttribute('data-theme', settings_theme); + localStorage.setItem('accent', settings_accent); + document.documentElement.setAttribute('data-accent', settings_accent); +} + //-------------------------------------------------------------------------------------- // Document ready function //-------------------------------------------------------------------------------------- $(document).ready(function () { + apply_settings($("#settings-theme").val(), $("#settings-accent").val()); "use strict"; // INITS diff --git a/dashmachine/static/js/main/home.js b/dashmachine/static/js/main/home.js new file mode 100644 index 0000000..c4bba42 --- /dev/null +++ b/dashmachine/static/js/main/home.js @@ -0,0 +1,30 @@ +var d = document.getElementById("dashboard-sidenav"); +d.className += " active theme-primary"; + + +$( document ).ready(function() { + $("#apps-filter").on('keyup', function(e) { + var value = $(this).val().toLowerCase(); + $(".app-a").each(function(i, e) { + if ($(this).attr("data-name").toLowerCase().indexOf(value) > -1 + || $(this).attr("data-description").toLowerCase().indexOf(value) > -1) { + $(this).removeClass('hide'); + } else { + $(this).addClass('hide'); + } + }); + }); + + $(".data-template").each(function(e) { + var el = $(this); + $.ajax({ + url: el.attr('data-url'), + type: 'GET', + data: {template: el.text()}, + success: function(data){ + el.text(data); + el.removeClass('hide'); + } + }); + }); +}); \ No newline at end of file diff --git a/dashmachine/static/js/settings_system/settings.js b/dashmachine/static/js/settings_system/settings.js index 6dba529..fc00bd1 100644 --- a/dashmachine/static/js/settings_system/settings.js +++ b/dashmachine/static/js/settings_system/settings.js @@ -1,13 +1,6 @@ var d = document.getElementById("settings-sidenav"); d.className += " active theme-primary"; -function apply_settings(settings_theme, settings_accent){ - localStorage.setItem('mode', settings_theme); - document.documentElement.setAttribute('data-theme', settings_theme); - localStorage.setItem('accent', settings_accent); - document.documentElement.setAttribute('data-accent', settings_accent); -} - $( document ).ready(function() { initTCdrop('#images-tcdrop'); $("#config-wiki-modal").modal(); @@ -20,7 +13,6 @@ $( document ).ready(function() { success: function(data){ if (data.data.msg === "success"){ M.toast({html: 'Config applied successfully'}); - apply_settings(data.data.settings.theme, data.data.settings.accent); location.reload(true); } else { M.toast({html: data.data.msg, classes: "theme-warning"}); @@ -93,4 +85,21 @@ $( document ).ready(function() { }); }); + $("#edit-user-btn").on('click', function(e) { + $.ajax({ + url: $(this).attr('data-url'), + type: 'POST', + data: $("#edit-user-form").serialize(), + success: function(data){ + if (data.data.err !== 'success'){ + M.toast({html: data.data.err, classes: 'theme-warning'}); + } else { + $("#user-form-password").val(''); + $("#user-form-confirm_password").val(''); + M.toast({html: 'User updated'}); + } + } + }); + }); + }); \ No newline at end of file diff --git a/dashmachine/templates/main/home.html b/dashmachine/templates/main/home.html index 9cd2397..e0b7a2f 100755 --- a/dashmachine/templates/main/home.html +++ b/dashmachine/templates/main/home.html @@ -40,16 +40,25 @@ {% endif %}
-
-
- +
+
{% if app.data_template %} -

- {{ app.data_template }} -

+
+
+ +
+ +
+

+ {{ app.data_template|safe }} +

+
+
+ {% else %} + {% endif %}
-
+
{{ app.name }}
{{ app.description }}
@@ -77,35 +86,5 @@ {% endblock page_vendor_js %} {% block page_lvl_js %} - + {{ process_js_sources(src="main/home.js")|safe }} {% endblock page_lvl_js %} diff --git a/dashmachine/templates/settings_system/settings.html b/dashmachine/templates/settings_system/settings.html index 089100a..4479389 100644 --- a/dashmachine/templates/settings_system/settings.html +++ b/dashmachine/templates/settings_system/settings.html @@ -25,7 +25,7 @@

Config.ini Readme

-
Settings Example
+
Settings Reference
[Settings]
theme = dark
@@ -42,7 +42,7 @@ Options - + [Settings] Yes @@ -70,7 +70,7 @@ -
App Example
+
App Reference
[App Name]
prefix = https://
@@ -91,7 +91,7 @@ Options - + [App Name] Yes @@ -143,6 +143,100 @@ +
Api Data Reference
+ + [variable_name]
+ platform = rest
+ resource = your-website.com
+ value_template = variable_name
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableRequiredDescriptionOptions
[variable_name]YesThe variable to be made available to apps.variable (python syntax)
platformYesPlatform for data sourcerest
resourceYesThe url for the api call.myapp.com/api/hello
value_templateNoTranform the data returned by the api call (python syntax)variable_name[0]['info']
methodNOT IMPLEMENTEDNOT IMPLEMENTEDNOT IMPLEMENTED
payloadNOT IMPLEMENTEDNOT IMPLEMENTEDNOT IMPLEMENTED
authenticationNOT IMPLEMENTEDNOT IMPLEMENTEDNOT IMPLEMENTED
usernameNOT IMPLEMENTEDNOT IMPLEMENTEDNOT IMPLEMENTED
passwordNOT IMPLEMENTEDNOT IMPLEMENTEDNOT IMPLEMENTED
+ +
Api Data Example
+

Say we wanted to display how many Pokemon there are using the PokeAPI, we would add the following to the config:

+ + [num_pokemon]
+ platform = rest
+ resource = https://pokeapi.co/api/v2/pokemon
+ value_template = num_pokemon['count']
+
+ +

Then in the config entry for the app you want to add this to, you would add:

+ + + data_template = Pokemon: {{ '{{ num_pokemon }}' }} + +
@@ -175,7 +269,7 @@
{{ input( size="s12", - class="materialize-textarea", + class="materialize-textarea code", form_obj=config_form.config, id="config-textarea" ) }} @@ -247,7 +341,7 @@
-
+
@@ -255,34 +349,39 @@
User
- {{ user_form.hidden_tag() }} - {{ input( - label="Username", - id="user-form-username", - size="s12", - form_obj=user_form.username, - val=current_user.username - ) }} + + {{ user_form.hidden_tag() }} - {{ input( - label="Password", - id="user-form-password", - form_obj=user_form.password, - size="s12" - ) }} + {{ input( + label="Username", + id="user-form-username", + size="s12", + form_obj=user_form.username, + val=current_user.username + ) }} - {{ input( - label="Confirm Password", - id="user-form-confirm_password", - form_obj=user_form.confirm_password, - required='required', - size="s12" - ) }} + {{ input( + label="Password", + id="user-form-password", + form_obj=user_form.password, + size="s12" + ) }} + + {{ input( + label="Confirm Password", + id="user-form-confirm_password", + form_obj=user_form.confirm_password, + required='required', + size="s12" + ) }} + {{ button( icon="save", float="left", + id="edit-user-btn", + data={'url': url_for('settings_system.edit_user')}, text="save" ) }}
diff --git a/dashmachine/user_system/forms.py b/dashmachine/user_system/forms.py index 02d0b52..3edf26b 100755 --- a/dashmachine/user_system/forms.py +++ b/dashmachine/user_system/forms.py @@ -4,13 +4,13 @@ from wtforms import ( PasswordField, BooleanField, ) -from wtforms.validators import DataRequired +from wtforms.validators import DataRequired, Length class UserForm(FlaskForm): - username = StringField(validators=[DataRequired()]) + username = StringField(validators=[DataRequired(), Length(min=4, max=120)]) - password = PasswordField(validators=[DataRequired()]) + password = PasswordField(validators=[DataRequired(), Length(min=8, max=120)]) confirm_password = PasswordField() diff --git a/dashmachine/user_system/utils.py b/dashmachine/user_system/utils.py index f63bf13..9b981de 100755 --- a/dashmachine/user_system/utils.py +++ b/dashmachine/user_system/utils.py @@ -3,7 +3,10 @@ from dashmachine.user_system.models import User def add_edit_user(username, password, user_id=None): - user = User.query.filter_by(id=user_id).first() + if user_id: + user = User.query.filter_by(id=user_id).first() + else: + user = User.query.first() if not user: user = User()