Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed2ddb0a77 | ||
|
|
31bb032a4e | ||
|
|
22dcf36b14 | ||
|
|
088bf495f5 | ||
|
|
c0aa82241b | ||
|
|
9544463bd6 | ||
|
|
60cd5140d2 | ||
|
|
dcbc8dd062 | ||
|
|
08f232bf51 | ||
|
|
75d068fef6 | ||
|
|
373ce1247e | ||
|
|
eaa983e955 | ||
|
|
652bbba9c0 | ||
|
|
69d6ba277d | ||
|
|
8791c58cbf | ||
|
|
258a359ce1 | ||
|
|
21b210a689 | ||
|
|
430b144d92 | ||
|
|
d4cfa4815c | ||
|
|
9f8f89fde2 |
@@ -10,12 +10,18 @@ Dependencies:
|
|||||||
- flask
|
- flask
|
||||||
- pytest
|
- pytest
|
||||||
- coverage
|
- coverage
|
||||||
- libxapp-gtk3-module
|
|
||||||
- gettext
|
- gettext
|
||||||
|
|
||||||
Recommended:
|
Recommended:
|
||||||
- libjs-htmx (needed if the web front-end is to be used)
|
- libjs-htmx (needed if the web front-end is to be used)
|
||||||
- sass-stylesheets-bulma (needed if the web front-end is to be used)
|
- sass-stylesheets-bulma (needed if the web front-end is to be used)
|
||||||
|
- libxapp-gtk3-module
|
||||||
|
|
||||||
|
On Debian-based systems, you should get everything with the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
apt install python3-flask python3-command-runner python3-pytest python3-dmm gettext libjs-htmx sass-stylesheets-bulma fonts-fork-awesome
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
bp = Blueprint('install', __name__,
|
|
||||||
template_folder='')
|
|
||||||
|
|
||||||
from applets.install import routes
|
|
||||||
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
{% extends "layout.html" %}
|
|
||||||
{% block body %}
|
|
||||||
|
|
||||||
<center>
|
|
||||||
<p style="position: absolute: left: 45px; top: 10px;"> <big><big> Installing...</big></big></p> <br />
|
|
||||||
<img style="width: 400px; padding: 20px;" src="/static/slide1.png" /> <br />
|
|
||||||
<p> Installing system, the rest of the process is automated. </p>
|
|
||||||
<p style="margin: 20px;"> <input style="background-color: #777777;" type="checkbox" id="reboot" name="reboot" value="reboot" checked>
|
|
||||||
<label for="reboot"> Reboot automatically when ready </label></p><br>
|
|
||||||
</center>
|
|
||||||
|
|
||||||
<div style="position: absolute; padding: 10px; background-color: #26495e; left: 40px; right: 40px; bottom: 40px; height: text-align: middle;"> <center> Initializing... </center> </div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
from applets.install import bp
|
|
||||||
from flask import Flask, request, session, redirect, \
|
|
||||||
url_for, render_template, flash, Blueprint
|
|
||||||
from flask import current_app
|
|
||||||
|
|
||||||
@bp.route('/install',methods=['GET', 'POST', 'PUT'])
|
|
||||||
def install_index():
|
|
||||||
"""
|
|
||||||
The page you'd get if you access the root of
|
|
||||||
this app in a browser.
|
|
||||||
"""
|
|
||||||
install_start()
|
|
||||||
return render_template('install.html')
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/install-start',methods=['GET', 'POST', 'PUT'])
|
|
||||||
def install_start():
|
|
||||||
"""
|
|
||||||
Trigger the installation process
|
|
||||||
"""
|
|
||||||
print("The installation process is starting!... in theory at least")
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/install-status',methods=['GET', 'POST', 'PUT'])
|
|
||||||
def install_status():
|
|
||||||
"""
|
|
||||||
Update on the status of the installation process.
|
|
||||||
"""
|
|
||||||
print("installation en coers")
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/settings',methods=['GET', 'POST', 'PUT'])
|
|
||||||
def settings():
|
|
||||||
"""
|
|
||||||
Manage settings for the installation module.
|
|
||||||
"""
|
|
||||||
print("Settings")
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
bp = Blueprint('main', __name__,
|
|
||||||
template_folder='')
|
|
||||||
|
|
||||||
from applets.main import routes
|
|
||||||
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
from applets.main import bp
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/')
|
|
||||||
def index():
|
|
||||||
"""
|
|
||||||
The page you'd get if you access the root of
|
|
||||||
this app in a browser.
|
|
||||||
"""
|
|
||||||
return ("Welcome to System Installer Daemon POC <br />"
|
|
||||||
"Version: Unavailable")
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/api/v0')
|
|
||||||
def apihome():
|
|
||||||
"""
|
|
||||||
Not sure what this function should do, but have
|
|
||||||
a feeling that it should exist.
|
|
||||||
"""
|
|
||||||
return ("0")
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
bp = Blueprint('software', __name__,
|
|
||||||
template_folder='')
|
|
||||||
|
|
||||||
from applets.software import routes
|
|
||||||
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
bp = Blueprint('users', __name__,
|
|
||||||
template_folder='')
|
|
||||||
|
|
||||||
from applets.users import routes
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
bp = Blueprint('webui', __name__)
|
|
||||||
|
|
||||||
from applets.webui import routes
|
|
||||||
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
from applets.webui import bp
|
|
||||||
from flask import Flask, request, session, redirect, \
|
|
||||||
url_for, render_template, flash, Blueprint
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/webui')
|
|
||||||
def webui_index():
|
|
||||||
"""
|
|
||||||
The page you'd get if you access the root of
|
|
||||||
this app in a browser.
|
|
||||||
"""
|
|
||||||
return ("""
|
|
||||||
<head>
|
|
||||||
<script src="/static/htmx.min.js.gz crossorigin="anonymous"></script>
|
|
||||||
</head>
|
|
||||||
<button hx-post="/clicked"
|
|
||||||
hx-trigger="click"
|
|
||||||
hx-target="#parent-div"
|
|
||||||
hx-swap="outerHTML" >
|
|
||||||
Click Me!
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
|
||||||
<div style="background-color: black; color: white; height: 200px; width: 200px;" hx-get="/welcome" hx-trigger="every 2s"></div>
|
|
||||||
<div hx-post="/welcome" hx-trigger="mouseenter">
|
|
||||||
1
|
|
||||||
<br><br><br><br>
|
|
||||||
[Here Mouse, Mouse!]
|
|
||||||
<br><Br><br><br>
|
|
||||||
2
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Welcome to System Installer Daemon POC <br />
|
|
||||||
This is the WebUI Index
|
|
||||||
""")
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/webui/welcome')
|
|
||||||
def webui_welcome():
|
|
||||||
"""
|
|
||||||
Welcome screen for the webui.
|
|
||||||
|
|
||||||
It's job right now is to:
|
|
||||||
|
|
||||||
- Obtain the language
|
|
||||||
- Check basic system eligibility
|
|
||||||
"""
|
|
||||||
return render_template('welcome.html')
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/webui/users')
|
|
||||||
def webui_users():
|
|
||||||
"""
|
|
||||||
Users screen for the webui.
|
|
||||||
|
|
||||||
It's job right now is to:
|
|
||||||
|
|
||||||
- Set up an initial user
|
|
||||||
|
|
||||||
More functions will follow at a later stage
|
|
||||||
"""
|
|
||||||
return render_template('users.html')
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/webui/disks')
|
|
||||||
def webui_disks():
|
|
||||||
"""
|
|
||||||
Disks screen for the webui.
|
|
||||||
"""
|
|
||||||
return render_template('disks.html')
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/webui/disks/partition/<part>')
|
|
||||||
def webui_disks_partition(part):
|
|
||||||
"""
|
|
||||||
Partition modal for the webui partition screen.
|
|
||||||
"""
|
|
||||||
return render_template('disks_partition.html')
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/webui/software')
|
|
||||||
def webui_software():
|
|
||||||
"""
|
|
||||||
Software screen for the webui.
|
|
||||||
"""
|
|
||||||
return render_template('software.html')
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/webui/summary')
|
|
||||||
def webui_summary():
|
|
||||||
"""
|
|
||||||
Summary screen for the webui.
|
|
||||||
"""
|
|
||||||
return render_template('summary.html')
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
bp = Blueprint('welcome', __name__,
|
|
||||||
template_folder='')
|
|
||||||
|
|
||||||
from applets.welcome import routes
|
|
||||||
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,112 +0,0 @@
|
|||||||
from applets.welcome import bp
|
|
||||||
from flask import Flask, request, session, redirect, \
|
|
||||||
url_for, render_template, flash, Blueprint
|
|
||||||
# we use this neat little trick to get config data from the main app
|
|
||||||
from flask import current_app
|
|
||||||
import gettext
|
|
||||||
import dmm.lsblk as lsblk
|
|
||||||
|
|
||||||
# Set up Gettext
|
|
||||||
def set_language(LANG):
|
|
||||||
"""
|
|
||||||
Sets language for this applet
|
|
||||||
"""
|
|
||||||
translations = gettext.translation("welcome", './applets/welcome/locales',
|
|
||||||
fallback=True, languages=[LANG])
|
|
||||||
translations.install()
|
|
||||||
_ = translations.gettext
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/welcome',methods=['GET', 'POST', 'PUT'])
|
|
||||||
def welcome_index():
|
|
||||||
"""
|
|
||||||
The page you'd get if you access the root of
|
|
||||||
this app in a browser.
|
|
||||||
"""
|
|
||||||
set_language(current_app.config['CONFIG']['settings']['language'])
|
|
||||||
if request.method == 'POST':
|
|
||||||
if "lang" in request.form.keys():
|
|
||||||
current_app.config['CONFIG']['settings']['language'] = request.form["lang"]
|
|
||||||
LANG = current_app.config['CONFIG']['settings']['language']
|
|
||||||
set_language(LANG)
|
|
||||||
FORMLANG = request.form["lang"]
|
|
||||||
if "keyboard" in request.form.keys():
|
|
||||||
print(request.form["keyboard"])
|
|
||||||
if "timezone" in request.form.keys():
|
|
||||||
print(request.form["timezone"])
|
|
||||||
global lang
|
|
||||||
lang = current_app.config['CONFIG']['settings']['language']
|
|
||||||
blkid = lsblk.list_scsi_devices()
|
|
||||||
string_dict = build_stringlist()
|
|
||||||
build_menu()
|
|
||||||
build_summary()
|
|
||||||
menu = current_app.config['CONFIG']['settings']['menu_order'].split(" ")
|
|
||||||
next_step_url = menu[menu.index("welcome")+1]
|
|
||||||
previous_step_url = menu[menu.index("welcome")-1]
|
|
||||||
|
|
||||||
print("index is: " , menu.index("welcome"))
|
|
||||||
if menu.index("welcome") == 0:
|
|
||||||
previous_step_url = False
|
|
||||||
else:
|
|
||||||
previous_step_url = menu[menu.index("users")-1]
|
|
||||||
|
|
||||||
print("next is: " + next_step_url)
|
|
||||||
print("previous is: " , previous_step_url)
|
|
||||||
power_button = '<button class="button is-dark"> <img width="16px;" src="/static/icons/greencheck.png"> Power: AC </button>'
|
|
||||||
internet_button = ' <button class="button is-dark"> <img width="16px;" src="/static/icons/greencheck.png"> Internet </button>'
|
|
||||||
bottom_menu = power_button + internet_button
|
|
||||||
|
|
||||||
return render_template('welcome.html',
|
|
||||||
string_dict=string_dict, selected_lang=lang,
|
|
||||||
menu=current_app.config['CONFIG']['settings']['menu'],
|
|
||||||
menu_order=current_app.config['CONFIG']['settings']['menu_order'].split(),
|
|
||||||
previous_step=previous_step_url,
|
|
||||||
next_step=next_step_url,
|
|
||||||
bottom_menu=bottom_menu)
|
|
||||||
|
|
||||||
|
|
||||||
def build_stringlist():
|
|
||||||
"""
|
|
||||||
Return all the strings that is used in this applet."
|
|
||||||
"""
|
|
||||||
string_dict = {}
|
|
||||||
string_dict['menu_item'] = _("Welcome")
|
|
||||||
string_dict['welcome_text'] = _("Welcome! This setup program will install Debian on to your system.")
|
|
||||||
string_dict['confirm_text'] = _("Please confirm the following details:")
|
|
||||||
string_dict['language_text'] = _("Language:")
|
|
||||||
string_dict['keylayout_text'] = _("Keyboard Layout:")
|
|
||||||
string_dict['timezone_text'] = _("Time Zone:")
|
|
||||||
string_dict['basicsettings_text'] = _("Basic Settings:")
|
|
||||||
lang_dict = {}
|
|
||||||
lang_dict['af'] = _("Afrikaans")
|
|
||||||
lang_dict['en'] = _("English (International)")
|
|
||||||
lang_dict['en-us'] = _("English (United States)")
|
|
||||||
lang_dict['en-uk'] = _("English (United Kingdom)")
|
|
||||||
lang_dict['en-za'] = _("English (South Africa)")
|
|
||||||
string_dict['lang_list'] = lang_dict
|
|
||||||
return string_dict
|
|
||||||
|
|
||||||
def build_menu():
|
|
||||||
"""
|
|
||||||
Define menu items and paths.
|
|
||||||
"""
|
|
||||||
current_app.config['CONFIG']['settings']['menu']['welcome'] = (build_stringlist()['menu_item'], "/welcome", 10)
|
|
||||||
|
|
||||||
|
|
||||||
def build_summary():
|
|
||||||
"""
|
|
||||||
Write up a summary of what this module will do.
|
|
||||||
"""
|
|
||||||
html = ("<b><big>Basic settings</big></b><p> Language: " + lang + "</p>")
|
|
||||||
if not 'Summary' in current_app.config['CONFIG']:
|
|
||||||
current_app.config['CONFIG']['Summary'] = {}
|
|
||||||
current_app.config['CONFIG']['Summary']['welcome'] = {}
|
|
||||||
current_app.config['CONFIG']['Summary']['welcome']['heading'] = "Basic Settings"
|
|
||||||
print(current_app.config['CONFIG']['Summary']['welcome'])
|
|
||||||
text = "Language: " + str(current_app.config['CONFIG']['settings']['language'])
|
|
||||||
current_app.config['CONFIG']['Summary']['welcome']['text'] = text
|
|
||||||
return(html)
|
|
||||||
|
|
||||||
|
|
||||||
set_language(current_app.config['CONFIG']['settings']['language'])
|
|
||||||
build_menu
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
{% extends "layout.html" %}
|
|
||||||
{% block body %}
|
|
||||||
|
|
||||||
<img style="width: 100%; border-radius: 8px;"
|
|
||||||
src="/static/applets/welcome/img/banner.png"
|
|
||||||
alt="Debian Image banner" />
|
|
||||||
|
|
||||||
<p><b> {{ string_dict['welcome_text'] }} </b></p>
|
|
||||||
<p>{{ string_dict['confirm_text'] }} </p> <br />
|
|
||||||
|
|
||||||
<div style="padding-left: 15px;">
|
|
||||||
|
|
||||||
<form action="/welcome" method="POST">
|
|
||||||
<i class="fa fa-language" aria-hidden="true"></i> {{ string_dict['language_text'] }}
|
|
||||||
<div class="control is-link" width="180px">
|
|
||||||
<div class="select">
|
|
||||||
<select hx-post="/welcome" hx-target="body" name="lang" style="width: 220px">
|
|
||||||
{% for lang in string_dict['lang_list'] %}
|
|
||||||
<option value="{{lang}}" {% if lang == selected_lang %} selected=selected {% endif %}>{{ string_dict['lang_list'][lang] }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<i class="fa fa-keyboard-o" aria-hidden="true"></i> {{ string_dict['keylayout_text'] }}
|
|
||||||
<div class="control is-link">
|
|
||||||
<div class="select">
|
|
||||||
<select hx-post="/welcome" hx-target="body" name="keyboard" style="width: 220px">
|
|
||||||
<option>en-us</option>
|
|
||||||
<option>en-uk</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<i class="fa fa-clock-o" aria-hidden="true"></i> {{ string_dict['timezone_text'] }}
|
|
||||||
<div class="control is-link">
|
|
||||||
<div class="select">
|
|
||||||
<select hx-post="/welcome" hx-target="body" name="timezone" style="width: 220px">
|
|
||||||
<option>Africa/Johannesburg</option>
|
|
||||||
<option>UTC</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../applets/welcome/img
|
|
||||||
|
Before Width: | Height: | Size: 304 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="m 8 0 c -4.40625 0 -8 3.59375 -8 8 s 3.59375 8 8 8 s 8 -3.59375 8 -8 s -3.59375 -8 -8 -8 z m 3.398438 4.507812 c 0.265624 -0.027343 0.527343 0.050782 0.734374 0.21875 c 0.425782 0.351563 0.488282 0.980469 0.140626 1.40625 l -4.5 5.5 c -0.179688 0.21875 -0.441407 0.351563 -0.722657 0.367188 c -0.28125 0.011719 -0.558593 -0.09375 -0.757812 -0.292969 l -2.5 -2.5 c -0.390625 -0.390625 -0.390625 -1.023437 0 -1.414062 s 1.023437 -0.390625 1.414062 0 l 1.71875 1.71875 l 3.800781 -4.644531 c 0.167969 -0.203126 0.410157 -0.335938 0.671876 -0.363282 z m 0 0" fill="#2e3436"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 719 B |
|
Before Width: | Height: | Size: 35 KiB |
@@ -1,53 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
width="16"
|
|
||||||
height="16"
|
|
||||||
version="1.1"
|
|
||||||
id="svg2"
|
|
||||||
sodipodi:docname="keyboard.svg"
|
|
||||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview2"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:zoom="52.375"
|
|
||||||
inkscape:cx="8"
|
|
||||||
inkscape:cy="8"
|
|
||||||
inkscape:window-width="1236"
|
|
||||||
inkscape:window-height="1041"
|
|
||||||
inkscape:window-x="662"
|
|
||||||
inkscape:window-y="199"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="svg2" />
|
|
||||||
<g
|
|
||||||
font-weight="400"
|
|
||||||
fill="#474747"
|
|
||||||
id="g2"
|
|
||||||
style="fill:#c0bfbc">
|
|
||||||
<path
|
|
||||||
d="M3.702 1C2.17 1 .984 2.32.984 3.844v8.344c0 1.524 1.185 2.843 2.718 2.843h8.58c1.532 0 2.75-1.32 2.75-2.844V3.845c0-1.525-1.218-2.844-2.75-2.844zm.782 1.031c3.526.256 5.317.134 7.047 0 .754-.058 1.532.616 1.532 1.438v7.375c0 .665-.532 1.095-1.188 1.187-2.836.397-4.753.44-7.673 0-.655-.099-1.187-.522-1.187-1.187V3.5c0-.822.714-1.524 1.469-1.469z"
|
|
||||||
style="line-height:normal;-inkscape-font-specification:'Bitstream Vera Sans';text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;marker:none;fill:#c0bfbc"
|
|
||||||
color="#bebebe"
|
|
||||||
font-family="Bitstream Vera Sans"
|
|
||||||
overflow="visible"
|
|
||||||
id="path1" />
|
|
||||||
<path
|
|
||||||
d="M10.564 5.977l-2.939.044.016 1 2.879-.043c.2.018.33.076.396.135.067.06.105.121.105.293l-.008.604H8.517l.037.002a1.457 1.457 0 00-1.164.43 1.558 1.558 0 00-.416 1.023c-.013.367.092.75.352 1.053.26.303.687.496 1.162.482h3.482l.051-3.59v-.004c0-.402-.16-.786-.435-1.035-.276-.249-.63-.364-.998-.393zM8.48 9.01h2.519l-.014.99H8.457c-.22.007-.302-.051-.371-.133a.553.553 0 01-.112-.367.587.587 0 01.141-.371c.079-.083.163-.134.363-.12zm2.862-5.985l-3 1 .316.95 3-1z"
|
|
||||||
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;shape-padding:0;isolation:auto;mix-blend-mode:normal;marker:none;fill:#c0bfbc"
|
|
||||||
color="#000"
|
|
||||||
font-family="sans-serif"
|
|
||||||
overflow="visible"
|
|
||||||
id="path2" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.7 KiB |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 6 c 0 1.644531 1.355469 3 3 3 h 1 v 3 l 3 -3 h 6 c 1.644531 0 3 -1.355469 3 -3 v -6 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 0" fill="#2e3436"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 329 B |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 6 c 0 1.644531 1.355469 3 3 3 h 1 v 3 l 3 -3 h 6 c 1.644531 0 3 -1.355469 3 -3 v -6 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 2 h 10 c 0.554688 0 1 0.445312 1 1 v 6 c 0 0.554688 -0.445312 1 -1 1 h -10 c -0.570312 0 -1 -0.429688 -1 -1 v -6 c 0 -0.554688 0.445312 -1 1 -1 z m 0 0" fill="#2e3436" fill-opacity="0.34902"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 502 B |
@@ -1,20 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import webview
|
|
||||||
|
|
||||||
LOCATION = "http://localhost:8080/welcome"
|
|
||||||
|
|
||||||
def on_closed():
|
|
||||||
"""
|
|
||||||
Actions to take when System Installer is closed.
|
|
||||||
"""
|
|
||||||
print('pywebview window is closed')
|
|
||||||
|
|
||||||
|
|
||||||
window = webview.create_window('System Installer', LOCATION,
|
|
||||||
transparent=True, easy_drag=False, frameless=True,
|
|
||||||
width=1050, focus=True, zoomable=True,
|
|
||||||
confirm_close=True, resizable=True)
|
|
||||||
|
|
||||||
window.events.closed += on_closed
|
|
||||||
webview.start()
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#!/usr/bin/env dmm-perform-recipe
|
|
||||||
|
|
||||||
module_path:
|
|
||||||
- local
|
|
||||||
|
|
||||||
settings:
|
|
||||||
language: en
|
|
||||||
devmode: True
|
|
||||||
apt_depends: util-linux adduser parted e2fsprogs debootstrap
|
|
||||||
apps: main welcome users disks software summary install
|
|
||||||
menu_order: welcome users disks software summary
|
|
||||||
|
|
||||||
recipe:
|
|
||||||
installer_dependencies:
|
|
||||||
description: Installing Dependencies
|
|
||||||
module: aptpkg
|
|
||||||
function: install
|
|
||||||
packagooes: apt
|
|
||||||
chrooti: /tmp
|
|
||||||
users:
|
|
||||||
module: users
|
|
||||||
function: add
|
|
||||||
users:
|
|
||||||
- username:
|
|
||||||
password:
|
|
||||||
fullname:
|
|
||||||
sudo: True
|
|
||||||
popcon:
|
|
||||||
module: software
|
|
||||||
function: popcon
|
|
||||||
enable_popcon: False
|
|
||||||
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<!-- Buttons on the left -->
|
|
||||||
<div style="position: absolute; bottom: 15px; left: 15px;">
|
|
||||||
|
|
||||||
{% if previous_step %}
|
|
||||||
<a href="/{{ previous_step }}"><button class="button is-light">Back</button></a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if bottom_menu %}
|
|
||||||
{{ bottom_menu | safe }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Buttons on the right -->
|
|
||||||
<div style="position: absolute; bottom: 15px; right: 15px;">
|
|
||||||
{% if next_step %}
|
|
||||||
{% if next_step == "install" %}
|
|
||||||
<a href="/{{ next_step }}"><button hx-trigger="click, keyup[shiftKey&&key=='I'] from:body" class="button is-link">Install</button></a>
|
|
||||||
{% else %}
|
|
||||||
<a href="/{{ next_step }}"><button hx-trigger="click, keyup[shiftKey&&key=='N'] from:body" hx-target="/{{ next_step }}" class="button is-link">Next</button></a>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<!-- Header -->
|
|
||||||
<div id="titlebar" style="padding: 15px; margin: -15px; padding-bottom: 30px;">
|
|
||||||
|
|
||||||
<!-- drag region class: -->
|
|
||||||
<!-- <div id="titlebar" class="pywebview-drag-region" style="padding: 15px; margin: -15px; padding-bottom: 30px;"> -->
|
|
||||||
|
|
||||||
<button class="button is-link"> ☰ </button>
|
|
||||||
|
|
||||||
{% for item in menu_order %}
|
|
||||||
<a href="{{ menu[item][1]}}"> <button class="button is-{% if request.path == menu[item][1] %}info{% else %}dark{% endif %}"> {{ menu[item][0]}} </button></a>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
|
|
||||||
<div style="position: absolute; top: 15px; right: 15px;">
|
|
||||||
<a href="/help"> <button class="button is-light"> <b> ? </b> </button></a>
|
|
||||||
<button onclick="closeApp()" class="button is-danger" > 🗙 </button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div> <!-- end pywebview-drag-region -->
|
|
||||||
<!-- End Header -->
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<link href="/static/bulma.css" rel="stylesheet">
|
|
||||||
<link href="/static/system-installer.css" rel="stylesheet">
|
|
||||||
<link rel="shortcut icon" href="/static/icons/blippie.png" type="image/x-icon">
|
|
||||||
<link rel="stylesheet" href="/usr/share/fonts-fork-awesome/css/fork-awesome.css">
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css" integrity="sha256-XoaMnoYC5TH6/+ihMEnospgm0J1PM/nioxbOUdnM8HY=" crossorigin="anonymous">
|
|
||||||
<script src="/static/htmx.min.js" crossorigin="anonymous"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="frame">
|
|
||||||
{% include "header.html" %}
|
|
||||||
|
|
||||||
<div class="applet">
|
|
||||||
{% block body %}
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% include "footer.html" %}
|
|
||||||
|
|
||||||
</div> <!-- class "frame" -->
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Welcome to SID - The System Installer Daemon!
|
Welcome to YaSID - The The Yasi System Installer Daemon!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from flask import Flask, request, session, redirect, \
|
from flask import Flask, request, session, redirect, \
|
||||||
@@ -10,9 +10,10 @@ import logging
|
|||||||
import dmm.lsblk as lsblk
|
import dmm.lsblk as lsblk
|
||||||
import importlib
|
import importlib
|
||||||
import yaml
|
import yaml
|
||||||
|
import sys
|
||||||
|
|
||||||
# configuration
|
# configuration
|
||||||
CONFIGFILE="templates/dmm-installer-template.yaml"
|
CONFIGFILE="/etc/yasi/yasi.yaml"
|
||||||
|
|
||||||
# import config
|
# import config
|
||||||
global config
|
global config
|
||||||
@@ -27,6 +28,7 @@ app.config.from_object(__name__)
|
|||||||
app.config['CONFIG'] = config
|
app.config['CONFIG'] = config
|
||||||
app.app_context().push()
|
app.app_context().push()
|
||||||
config['settings']['menu'] = {}
|
config['settings']['menu'] = {}
|
||||||
|
sys.path.append('/usr/share/yasi-daemon')
|
||||||
|
|
||||||
if DEV_MODE:
|
if DEV_MODE:
|
||||||
print("Note: Starting in devmode!")
|
print("Note: Starting in devmode!")
|
||||||
@@ -37,7 +39,7 @@ if DEV_MODE:
|
|||||||
for APP in APPS.split(" "):
|
for APP in APPS.split(" "):
|
||||||
print(f"Loading applet: {APP} ")
|
print(f"Loading applet: {APP} ")
|
||||||
# Dynamically import the blueprint module
|
# Dynamically import the blueprint module
|
||||||
module = importlib.import_module(f"applets.{APP}")
|
module = importlib.import_module(f"yasi_applets.{APP}")
|
||||||
# Get the blueprint (bp) from the imported module
|
# Get the blueprint (bp) from the imported module
|
||||||
bp = getattr(module, "bp")
|
bp = getattr(module, "bp")
|
||||||
# Register the blueprint with the app
|
# Register the blueprint with the app
|
||||||
@@ -52,8 +54,8 @@ if DEV_MODE == "1":
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
serve(app,
|
serve(app,
|
||||||
host='0.0.0.0',
|
host='127.0.0.1',
|
||||||
port=8080,
|
port=9274,
|
||||||
url_scheme='http',
|
url_scheme='http',
|
||||||
expose_tracebacks=DEV_MODE)
|
expose_tracebacks=DEV_MODE)
|
||||||
|
|
||||||
35
src/yasi-webclient
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import webview
|
||||||
|
|
||||||
|
LOCATION = "http://localhost:9274/welcome"
|
||||||
|
|
||||||
|
def on_closed():
|
||||||
|
"""
|
||||||
|
Actions to take when System Installer is closed.
|
||||||
|
"""
|
||||||
|
print('pywebview window is closed')
|
||||||
|
|
||||||
|
|
||||||
|
window = webview.create_window('System Installer', LOCATION,
|
||||||
|
transparent=True, easy_drag=False, frameless=True,
|
||||||
|
width=1050, focus=True, zoomable=True,
|
||||||
|
confirm_close=True, resizable=True, shadow=True,
|
||||||
|
text_select=False, draggable=False
|
||||||
|
)
|
||||||
|
|
||||||
|
webview.settings = {
|
||||||
|
'ALLOW_DOWNLOADS': False,
|
||||||
|
'ALLOW_FILE_URLS': False,
|
||||||
|
'DRAG_REGION_SELECTOR': '.pywebview-drag-region',
|
||||||
|
'DRAG_REGION_DIRECT_TARGET_ONLY': True,
|
||||||
|
'OPEN_EXTERNAL_LINKS_IN_BROWSER': True,
|
||||||
|
'OPEN_DEVTOOLS_IN_DEBUG': True,
|
||||||
|
'IGNORE_SSL_ERRORS': False,
|
||||||
|
'REMOTE_DEBUGGING_PORT': None,
|
||||||
|
'SHOW_DEFAULT_MENUS': True
|
||||||
|
}
|
||||||
|
|
||||||
|
window.events.closed += on_closed
|
||||||
|
#webview.start(icon='/usr/share/icons/yasi.png')
|
||||||
|
webview.start()
|
||||||
0
src/yasi_applets/__init__.py
Normal file
@@ -3,5 +3,5 @@ from flask import Blueprint
|
|||||||
bp = Blueprint('disks', __name__,
|
bp = Blueprint('disks', __name__,
|
||||||
template_folder='')
|
template_folder='')
|
||||||
|
|
||||||
from applets.disks import routes
|
from yasi_applets.disks import routes
|
||||||
|
|
||||||
@@ -9,8 +9,9 @@
|
|||||||
|
|
||||||
<div class="radios">
|
<div class="radios">
|
||||||
<label class="radio">
|
<label class="radio">
|
||||||
<input type="radio" name="rsvp" />
|
<input selected type="radio" name="rsvp" />
|
||||||
Preconfigured partitioning
|
Preconfigured partitioning
|
||||||
|
<!-- Let's hide these babies for the initial release.
|
||||||
<label class="radio">
|
<label class="radio">
|
||||||
<input type="radio" name="rsvp" disabled />
|
<input type="radio" name="rsvp" disabled />
|
||||||
Erase entire disk
|
Erase entire disk
|
||||||
@@ -23,10 +24,11 @@
|
|||||||
<input type="radio" name="rsvp" disabled />
|
<input type="radio" name="rsvp" disabled />
|
||||||
Edit existing partitions
|
Edit existing partitions
|
||||||
</label>
|
</label>
|
||||||
|
-->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="columns" width="100%">
|
<div class="columns" width="100%">
|
||||||
<div class="column"><p> <br>Proposed layout: </p></div>
|
<div class="column"><p> <br>Current layout: </p></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -64,10 +66,9 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
|
|
||||||
<!-- {% for disk in blockdevs["blockdevices"] if disk["name"] != "zram0"%} -->
|
{% for disk in blockdevs["blockdevices"] if disk["name"] != "zram0" and "loop" not in disk["name"] and disk["name"] != "sr0" %}
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
<h1> Raw data </h1>
|
<h1> Raw data </h1>
|
||||||
{{ disk }}
|
{{ disk }}
|
||||||
|
|
||||||
@@ -137,17 +138,40 @@ fssize: {{ child['fssize'] }}
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<br>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<!-- Add Undetected Disk
|
<!-- Add Undetected Disk
|
||||||
Add Virtual Filesystem
|
Add Virtual Filesystem
|
||||||
Add Network Filesystem -->
|
Add Network Filesystem -->
|
||||||
|
|
||||||
|
<div class="columns" width="100%">
|
||||||
|
<div class="column"><p> <br>Proposed partitioning: </p></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style=""> <!-- partition bars -->
|
||||||
|
<div style="background-color: gray; padding: 4px 6px 7px 6px; border-radius: 10px;">
|
||||||
|
<p> <span style="width: 100%; border-radius: 8px 8px 0 0;" class="tag is-black">
|
||||||
|
<small><small> New GPT Partition Table</small></small>
|
||||||
|
<div class="columns">
|
||||||
|
{% for partition in partitions %}
|
||||||
|
{% if "mkpart" in partition['command'] %}
|
||||||
|
<a hx-get="/disks/partition/{{ partition['device'] }}" hx-swap="outerHTML"/ style="{% if "100%" in partition['command'] %}width: 100%; {% endif %}">
|
||||||
|
<div class="column is-narrow is-primary">
|
||||||
|
<div class="box" style="min-width: 220px; border-radius: 0 0 0px 5px; height: 60px; padding-top: 5px;">
|
||||||
|
<p class="is-tiny"> {{ partition['device'] }} </p>
|
||||||
|
<p class="title is-5"><span class="tag is-black"> {{ partition['mountpoint'] }} </span>
|
||||||
|
<span class="tag is-link"> {{ partition['fstype'] }} </span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from applets.disks import bp
|
from yasi_applets.disks import bp
|
||||||
from flask import Flask, request, session, redirect, \
|
from flask import Flask, request, session, redirect, \
|
||||||
url_for, render_template, flash, Blueprint
|
url_for, render_template, flash, Blueprint
|
||||||
import dmm.lsblk as lsblk
|
import dmm.lsblk as lsblk
|
||||||
@@ -21,14 +21,18 @@ def disks():
|
|||||||
add_disks_button = ' <button class="button iis-info"> <i class="fa fa-hdd-o" aria-hidden="true"></i> Add Disk or Filesystem </button>'
|
add_disks_button = ' <button class="button iis-info"> <i class="fa fa-hdd-o" aria-hidden="true"></i> Add Disk or Filesystem </button>'
|
||||||
add_swap_button = ' <button class="button iis-info"> <i class="fa fa-object-group" aria-hidden="true"></i> Swap Configuration </button>'
|
add_swap_button = ' <button class="button iis-info"> <i class="fa fa-object-group" aria-hidden="true"></i> Swap Configuration </button>'
|
||||||
bottom_menu = add_disks_button + add_swap_button
|
bottom_menu = add_disks_button + add_swap_button
|
||||||
|
# no bottom menu for this release
|
||||||
|
bottom_menu = ""
|
||||||
build_summary()
|
build_summary()
|
||||||
|
|
||||||
return render_template('disks.html', blockdevs=blockdevs,
|
return render_template('disks.html', blockdevs=blockdevs,
|
||||||
menu=current_app.config['CONFIG']['settings']['menu'],
|
menu=current_app.config['CONFIG']['settings']['menu'],
|
||||||
menu_order=current_app.config['CONFIG']['settings']['menu_order'].split(),
|
menu_order=current_app.config['CONFIG']['settings']['menu_order'].split(),
|
||||||
previous_step = previous_step_url,
|
previous_step = previous_step_url,
|
||||||
next_step = next_step_url,
|
next_step=next_step_url,
|
||||||
bottom_menu = bottom_menu)
|
partitions=current_app.config['CONFIG']['recipe']['create_partitions']['command_set'],
|
||||||
|
format_partitions=current_app.config['CONFIG']['recipe']['format_partitions'],
|
||||||
|
bottom_menu=bottom_menu)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/disks/partition/<part>')
|
@bp.route('/disks/partition/<part>')
|
||||||
7
src/yasi_applets/hardware/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('hardware', __name__,
|
||||||
|
template_folder='')
|
||||||
|
|
||||||
|
from yasi_applets.hardware import routes
|
||||||
|
|
||||||
41
src/yasi_applets/hardware/hardware.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<p> <b> Would you like fries with that? </b></p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div style="background-color: gray; padding: 4px 6px 7px 6px;
|
||||||
|
border-radius: 10px; margin-bottom: 20px;">
|
||||||
|
<span style="width: 100%; border-radius: 8px 8px 0 0;"
|
||||||
|
class="tag is-black">
|
||||||
|
Real-time Clock
|
||||||
|
</span>
|
||||||
|
<div style="padding-left: 15px; padding-right: 15px; background-color: #fff;
|
||||||
|
color: #000;">
|
||||||
|
<p>Date / time. / timezone</p> <br>
|
||||||
|
<input style="background-color: #777777;" type="checkbox" id="popcon"
|
||||||
|
name="popcon" hx-post="/software/settings" hx-trigger="change"
|
||||||
|
{% if popcon %} checked {% endif %}>
|
||||||
|
<label for="popcon"> Participate in PopCon </label><br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background-color: gray; padding: 4px 6px 7px 6px;
|
||||||
|
border-radius: 10px; margin-bottom: 20px;">
|
||||||
|
<span style="width: 100%; border-radius: 8px 8px 0 0;"
|
||||||
|
class="tag is-black">
|
||||||
|
Firmware
|
||||||
|
</span>
|
||||||
|
<div style="padding-left: 15px; padding-right: 15px; background-color: #fff;
|
||||||
|
color: #000;">
|
||||||
|
<p>Install additional firmware.</p> <br>
|
||||||
|
<input style="background-color: #777777;" type="checkbox" id="popcon"
|
||||||
|
name="popcon" hx-post="/software/settings" hx-trigger="change"
|
||||||
|
{% if popcon %} checked {% endif %}>
|
||||||
|
<label for="popcon"> Participate in PopCon </label><br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
65
src/yasi_applets/hardware/routes.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
from yasi_applets.hardware import bp
|
||||||
|
from flask import Flask, request, session, redirect, \
|
||||||
|
url_for, render_template, flash, Blueprint
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
@bp.route('/hardware')
|
||||||
|
def webui_hardware():
|
||||||
|
"""
|
||||||
|
Hardware screen for the webui.
|
||||||
|
"""
|
||||||
|
menu = current_app.config['CONFIG']['settings']['menu_order'].split(" ")
|
||||||
|
next_step_url = menu[menu.index("hardware")+1]
|
||||||
|
if menu[menu.index("hardware")] == 1:
|
||||||
|
previous_step_url = False
|
||||||
|
else:
|
||||||
|
previous_step_url = menu[menu.index("hardware")-1]
|
||||||
|
|
||||||
|
sources_button = ' <button class="button iis-info"> <i class="fa fa-cloud-download" aria-hidden="true"></i> Configure Network </button>'
|
||||||
|
blends_button = ' <button class="button iis-info"> <i class="fa fa-download" aria-hidden="true"></i> Install a Blend </button>'
|
||||||
|
bottom_menu = sources_button + blends_button
|
||||||
|
build_summary()
|
||||||
|
|
||||||
|
return render_template('hardware.html',
|
||||||
|
menu=current_app.config['CONFIG']['settings']['menu'],
|
||||||
|
menu_order=current_app.config['CONFIG']['settings']['menu_order'].split(),
|
||||||
|
previous_step = previous_step_url,
|
||||||
|
next_step = next_step_url,
|
||||||
|
bottom_menu = bottom_menu,
|
||||||
|
popcon=current_app.config['CONFIG']['recipe']['popcon']['enable_popcon'])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/hardware/settings', methods=['GET', 'POST'])
|
||||||
|
def hardware_settings():
|
||||||
|
"""
|
||||||
|
Receive settings for the hardware applet.
|
||||||
|
"""
|
||||||
|
if request.method == 'POST':
|
||||||
|
popcon = "popcon" in request.form
|
||||||
|
current_app.config['CONFIG']['recipe']['popcon']['enable_popcon'] = popcon
|
||||||
|
print(current_app.config['CONFIG']['recipe']['popcon']['enable_popcon'])
|
||||||
|
build_summary()
|
||||||
|
return ('', 204)
|
||||||
|
|
||||||
|
|
||||||
|
def build_menu():
|
||||||
|
"""
|
||||||
|
Define menu items and paths.
|
||||||
|
"""
|
||||||
|
# proper one once translations are done:
|
||||||
|
#current_app.config['CONFIG']['settings']['menu']['welcome'] = (build_stringlist()['menu_item'], "/welcome", 10)
|
||||||
|
current_app.config['CONFIG']['settings']['menu']['hardware'] = ("Hardware", "/hardware", 40)
|
||||||
|
|
||||||
|
|
||||||
|
def build_summary():
|
||||||
|
"""
|
||||||
|
Write up a summary of what this module will do.
|
||||||
|
"""
|
||||||
|
current_app.config['CONFIG']['Summary']['hardware'] = {}
|
||||||
|
current_app.config['CONFIG']['Summary']['hardware']['heading'] = "Hardware"
|
||||||
|
current_app.config['CONFIG']['Summary']['hardware']['bleh'] = current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']
|
||||||
|
current_app.config['CONFIG']['Summary']['hardware']['text'] = "Participate in Popularity Contest: " + str(current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']) + "<br/>No desktop environment selected."
|
||||||
|
return("ok?")
|
||||||
|
|
||||||
|
|
||||||
|
build_menu()
|
||||||
9
src/yasi_applets/install/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('install', __name__,
|
||||||
|
template_folder='',
|
||||||
|
static_folder='static',
|
||||||
|
static_url_path='/welcome/static')
|
||||||
|
|
||||||
|
from yasi_applets.install import routes
|
||||||
|
|
||||||
52
src/yasi_applets/install/install.html
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<p style="position: absolute: left: 45px; top: 10px;">
|
||||||
|
<big><big>
|
||||||
|
Installing...
|
||||||
|
</big></big>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<img style="width: 400px; padding: 20px;" src="/install/static/img/slide1.png" /> <br />
|
||||||
|
<p>
|
||||||
|
Installing system, the rest of the process is automated.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p style="margin: 20px;">
|
||||||
|
<input style="background-color: #777777;" type="checkbox"
|
||||||
|
id="reboot" name="reboot" value="reboot" checked>
|
||||||
|
<label for="reboot"> Reboot automatically when ready </label></p><br>
|
||||||
|
|
||||||
|
<div id="output"></div>
|
||||||
|
|
||||||
|
<!-- Hidden input to track last line -->
|
||||||
|
<div id="last-line-container">
|
||||||
|
<input type="hidden" id="last-line" name="last_line" value="0">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Poller -->
|
||||||
|
<div hx-get="/install/status"
|
||||||
|
hx-trigger="load, every 1s"
|
||||||
|
hx-include="#last-line"
|
||||||
|
hx-swap-oob="true"
|
||||||
|
hx-target="this"
|
||||||
|
hx-ext="json-enc"
|
||||||
|
hx-vars="{}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</center>
|
||||||
|
|
||||||
|
<div style="position: absolute; padding: 10px; background-color: #26495e; left: 40px;
|
||||||
|
right: 40px; bottom: 40px; height: text-align: middle;">
|
||||||
|
<center> Initializing... </center>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
109
src/yasi_applets/install/routes.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
from yasi_applets.install import bp
|
||||||
|
from flask import Flask, request, session, redirect, \
|
||||||
|
url_for, render_template, flash, Blueprint, jsonify
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
status = {
|
||||||
|
"status": "idle", # idle | running | finished
|
||||||
|
"output": "",
|
||||||
|
"exit_code": None,
|
||||||
|
"lines": []
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/install',methods=['GET', 'POST', 'PUT'])
|
||||||
|
def install_index():
|
||||||
|
"""
|
||||||
|
The page you'd get if you access the root of
|
||||||
|
this app in a browser.
|
||||||
|
"""
|
||||||
|
install_start()
|
||||||
|
return render_template('install.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/install-start',methods=['GET', 'POST', 'PUT'])
|
||||||
|
def install_start():
|
||||||
|
"""
|
||||||
|
Trigger the installation process
|
||||||
|
"""
|
||||||
|
print("The installation process is starting!... in theory at least")
|
||||||
|
if status["status"] == "running":
|
||||||
|
return jsonify({"status": "already running"}), 409 # Conflict
|
||||||
|
threading.Thread(target=run_script).start()
|
||||||
|
return jsonify({"status": "started"})
|
||||||
|
print("did it finish?")
|
||||||
|
|
||||||
|
|
||||||
|
def run_script():
|
||||||
|
global status
|
||||||
|
status["status"] = "running"
|
||||||
|
|
||||||
|
process = subprocess.Popen(
|
||||||
|
["bash", "/data/jonathan/devel/highvoltage/system-installer/daemon/src/fake-install-shell.sh"],
|
||||||
|
stdout = subprocess.PIPE,
|
||||||
|
stderr = subprocess.STDOUT,
|
||||||
|
text = True)
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
for line in iter(process.stdout.readline,''):
|
||||||
|
#lines.append(line.strip())
|
||||||
|
#status["output"] = "\n".join(lines)
|
||||||
|
status["lines"].append(line.strip())
|
||||||
|
|
||||||
|
process.wait()
|
||||||
|
status["status"] = 'finished'
|
||||||
|
status["exit_code"] = process.returncode
|
||||||
|
|
||||||
|
print(lines)
|
||||||
|
print("status:", status["status"], "code:", status["exit_code"])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/install/status', methods=['GET', 'POST'])
|
||||||
|
def install_status():
|
||||||
|
"""
|
||||||
|
Update on the status of the installation process.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Keep track of the last line posted, so that we can include
|
||||||
|
# any new lines not provided to the UI yet
|
||||||
|
last_line = int(request.args.get("last_line", 0))
|
||||||
|
new_lines = status["lines"][last_line:]
|
||||||
|
|
||||||
|
if not new_lines and status["status"] == "finished":
|
||||||
|
return "" # Empty response = HTMX will stop polling
|
||||||
|
|
||||||
|
lines_html = ""
|
||||||
|
for i, line in enumerate(new_lines, start=last_line + 1):
|
||||||
|
lines_html += f'<div>{line}</div>'
|
||||||
|
|
||||||
|
return {
|
||||||
|
"output": status['output'],
|
||||||
|
"status": status['status'],
|
||||||
|
"lines": lines_html,
|
||||||
|
"last_line": f'<input type="hidden" id="last-line" name="last_line" value="{last_line + len(new_lines)}">'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/install/cancel', methods=["POST"])
|
||||||
|
def install_cancel():
|
||||||
|
"""
|
||||||
|
Cancel the installation process.
|
||||||
|
"""
|
||||||
|
if status["status"] != "running" or not status["process"]:
|
||||||
|
return Response("No running script", status=400)
|
||||||
|
process["process"].terminate()
|
||||||
|
process["status"] = "cancelled"
|
||||||
|
process["exit_code"] = -1
|
||||||
|
return Response("Cancelled", status=200)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/settings',methods=['GET', 'POST', 'PUT'])
|
||||||
|
def settings():
|
||||||
|
"""
|
||||||
|
Manage settings for the installation module.
|
||||||
|
"""
|
||||||
|
print("Settings")
|
||||||
BIN
src/yasi_applets/install/static/img/slide1.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
9
src/yasi_applets/main/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('main', __name__,
|
||||||
|
template_folder='',
|
||||||
|
static_folder='static',
|
||||||
|
static_url_path='/main/static')
|
||||||
|
|
||||||
|
from yasi_applets.main import routes
|
||||||
|
|
||||||
36
src/yasi_applets/main/footer.html
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<!-- Buttons on the left -->
|
||||||
|
<div style="position: absolute; bottom: 15px; left: 15px;">
|
||||||
|
|
||||||
|
{% if previous_step %}
|
||||||
|
<!-- Why two of these? So that we can use two different keyboard shortcuts for back. -->
|
||||||
|
<button style="display: none;" hx-get="/{{ previous_step }}" hx-target="body"
|
||||||
|
hx-trigger="click, keydown[altKey&&key=='b'] from:body"></button>
|
||||||
|
<a href="/{{ previous_step }}"><button hx-get="/{{ previous_step }}" hx-target="body"
|
||||||
|
hx-trigger="click, keydown[ctrlKey&&code=='PageUp'] from:body" class="button is-light">Back</button></a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if bottom_menu %}
|
||||||
|
{{ bottom_menu | safe }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div> <!-- end buttons on the left -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Buttons on the right -->
|
||||||
|
<div style="position: absolute; bottom: 15px; right: 15px;">
|
||||||
|
|
||||||
|
{% if next_step %}
|
||||||
|
|
||||||
|
{% if next_step == "install" %}
|
||||||
|
<a href="/{{ next_step }}"><button hx-get="/{{ next_step }}" hx-target="body"
|
||||||
|
hx-trigger="click, keyup[altKey&&key=='i'] from:body" class="button is-link">Install</button></a>
|
||||||
|
{% else %}
|
||||||
|
<!-- Why two of these? So that we can use two different keyboard shortcuts for next. -->
|
||||||
|
<a href="/{{ next_step }}"<button hx-get="/{{ next_step }}" hx-target="body"
|
||||||
|
hx-trigger="click, keydown[ctrlKey&&code=='PageDown'] from:body" class=""></button></a>
|
||||||
|
<a href="/{{ next_step }}"<button hx-get="/{{ next_step }}" hx-target="body"
|
||||||
|
hx-trigger="click, keydown[altKey&&key=='n'] from:body" class="button is-link">Next</button></a>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div> <!-- end buttons on the right -->
|
||||||
28
src/yasi_applets/main/header.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- Header -->
|
||||||
|
<div id="titlebar" style="padding: 15px; margin: -15px; padding-bottom: 30px;">
|
||||||
|
|
||||||
|
<!-- drag region class: -->
|
||||||
|
<div id="titlebar" class="pywebview-drag-region" style="padding: 15px; margin: -15px; padding-bottom: 30px;">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
You might be tempted to replace the unicode character by a fa-code as in the
|
||||||
|
alternate commend below. Don't do it, it causes all kinds of artifacts and
|
||||||
|
glitches as the page reloads (and makes it feel much more like an old website
|
||||||
|
than a proper webapp.
|
||||||
|
-->
|
||||||
|
<a hx-get="/main/menu" hx-swap="outerHTML"/> <button class="button is-link"> ☰ </button> </a>
|
||||||
|
<!--
|
||||||
|
<a hx-get="/main/menu" hx-swap="outerHTML"/> <button class="button is-link"> <i class="fa fa-bars" aria-hidden="true"></i> </button> </a> -->
|
||||||
|
|
||||||
|
{% for item in menu_order %}
|
||||||
|
<a href="{{ menu[item][1]}}"> <button class="button is-{% if request.path == menu[item][1] %}info{% else %}dark{% endif %}"> {{ menu[item][0]}} </button></a>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
<div style="position: absolute; top: 15px; right: 15px;">
|
||||||
|
<a hx-get="/main/help" hx-swap="outerHTML"/> <button class="button is-light"> <i class="fa fa-question" aria-hidden="true"></i> </button></a>
|
||||||
|
<a hx-get="/main/quit" hx-swap="outerHTML"/><button onclick="closeApp()" class="button is-danger" > 🗙 </button></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div> <!-- end pywebview-drag-region -->
|
||||||
|
<!-- End Header -->
|
||||||
24
src/yasi_applets/main/help.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<div class="modal is-active">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<div style="background-color: #424242; padding: 15px; border-radius: 15px; boders: none; color: white;">
|
||||||
|
<h1 class="is-size-4"> Help </h1>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p>The help system is not yet implemented.</p>
|
||||||
|
<br>
|
||||||
|
<p>Some keyboard tips:<p>
|
||||||
|
<br>
|
||||||
|
<ul>
|
||||||
|
<li>ALT+n or CTRL+PGDn moves to the next page.</li>
|
||||||
|
<li>ALT+p or CTRL+PGUp moves to the previous page.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<div class="columns">
|
||||||
|
<a href="/welcome"><div class="column"><button class="button is-link">Continue</button></div></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
27
src/yasi_applets/main/layout.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link href="/main/static/bulma.css" rel="stylesheet">
|
||||||
|
<link href="/main/static/system-installer.css" rel="stylesheet">
|
||||||
|
<link rel="shortcut icon" href="/main/static/icons/blippie.png" type="image/x-icon">
|
||||||
|
<link rel="stylesheet" href="/main/static/fork-awesome.css">
|
||||||
|
<script src="/main/static/htmx.min.js" crossorigin="anonymous"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="frame">
|
||||||
|
{% include "header.html" %}
|
||||||
|
|
||||||
|
<div class="applet">
|
||||||
|
{% block body %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include "footer.html" %}
|
||||||
|
|
||||||
|
</div> <!-- class "frame" -->
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
17
src/yasi_applets/main/menu.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<div class="modal is-active">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<div style="background-color: #424242; padding: 15px; border-radius: 15px; borders: none; color: white;">
|
||||||
|
<h1 class="is-size-4"> Main menu </h1>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<p> There's nothing yet to do here.</p>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div class="columns">
|
||||||
|
<a href="/welcome"><div class="column"><button class="button is-link">Continue</button></div></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
19
src/yasi_applets/main/quit.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<div class="modal is-active">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<div style="background-color: #424242; padding: 15px; border-radius: 15px; boders: none; color: white;">
|
||||||
|
<h1 class="is-size-4"> Exit system installer </h1>
|
||||||
|
<br /><p class="title is-6"><span class="tag is-danger">Quitting is not yet implemented.</span>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<p> ALT+F4 will bring up a dialog that works though. </p>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div class="columns">
|
||||||
|
<a href="/welcome"><div class="column"><button class="button is-link">Continue</button></div></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
62
src/yasi_applets/main/routes.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
from yasi_applets.welcome import bp
|
||||||
|
from flask import Flask, request, session, redirect, \
|
||||||
|
url_for, render_template, flash, Blueprint
|
||||||
|
# we use this neat little trick to get config data from the main app
|
||||||
|
from flask import current_app
|
||||||
|
import gettext
|
||||||
|
|
||||||
|
# Set up Gettext
|
||||||
|
def set_language(LANG):
|
||||||
|
"""
|
||||||
|
Sets language for this applet
|
||||||
|
"""
|
||||||
|
# TODO: unhardcode this path
|
||||||
|
translations = gettext.translation("welcome", '/usr/share/yasi-daemon/yasi_applets/welcome/locales',
|
||||||
|
fallback=True, languages=[LANG])
|
||||||
|
translations.install()
|
||||||
|
_ = translations.gettext
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/')
|
||||||
|
def index():
|
||||||
|
"""
|
||||||
|
The page you'd get if you access the root of
|
||||||
|
this app in a browser.
|
||||||
|
"""
|
||||||
|
return ("Welcome to System Installer Daemon POC <br />"
|
||||||
|
"Version: Unavailable")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/main/help',methods=['GET'])
|
||||||
|
def main_welcome():
|
||||||
|
"""
|
||||||
|
Manages the main help system.
|
||||||
|
"""
|
||||||
|
return render_template('help.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/main/quit',methods=['GET'])
|
||||||
|
def main_quit():
|
||||||
|
"""
|
||||||
|
Manages the quit dialog.
|
||||||
|
"""
|
||||||
|
return render_template('quit.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/main/menu',methods=['GET'])
|
||||||
|
def main_menu():
|
||||||
|
"""
|
||||||
|
Manages the main menu.
|
||||||
|
"""
|
||||||
|
return render_template('menu.html')
|
||||||
|
|
||||||
|
|
||||||
|
def build_stringlist():
|
||||||
|
"""
|
||||||
|
Return all the strings that is used in this applet.
|
||||||
|
"""
|
||||||
|
string_dict = {}
|
||||||
|
string_dict['next_text'] = _("Next")
|
||||||
|
string_dict['previous_text'] = _("Previous")
|
||||||
|
return string_dict
|
||||||
|
|
||||||
1
src/yasi_applets/main/static/fork-awesome.css
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
/usr/share/fonts-fork-awesome/css/fork-awesome.css
|
||||||
BIN
src/yasi_applets/main/static/icons/highvoltage.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
src/yasi_applets/main/static/icons/keyboard.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 585 B After Width: | Height: | Size: 585 B |
BIN
src/yasi_applets/main/static/icons/yasi.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
@@ -10,6 +10,7 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 1050px;
|
min-width: 1050px;
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {margin: 0; height: 100%; overflow: hidden;}
|
html, body {margin: 0; height: 100%; overflow: hidden;}
|
||||||
@@ -23,19 +24,31 @@ html, body {margin: 0; height: 100%; overflow: hidden;}
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.applet a:link a:hover a:active {
|
.applet a:link a:hover a:active {
|
||||||
color: yellow;
|
color: yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.applet::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.applet {
|
.applet {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 442px;
|
height: 512px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow: -moz-scrollbars-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio:hover {
|
.radio:hover {
|
||||||
color: #f1f1f1;
|
color: #f1f1f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pywebview-drag-region {
|
||||||
|
width: 100%;
|
||||||
|
height: 85px;
|
||||||
|
}
|
||||||
9
src/yasi_applets/software/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('software', __name__,
|
||||||
|
template_folder='',
|
||||||
|
static_folder='static',
|
||||||
|
static_url_path='/software/static')
|
||||||
|
|
||||||
|
from yasi_applets.software import routes
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from applets.software import bp
|
from yasi_applets.software import bp
|
||||||
from flask import Flask, request, session, redirect, \
|
from flask import Flask, request, session, redirect, \
|
||||||
url_for, render_template, flash, Blueprint
|
url_for, render_template, flash, Blueprint
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
@@ -18,6 +18,8 @@ def webui_software():
|
|||||||
sources_button = ' <button class="button iis-info"> <i class="fa fa-cloud-download" aria-hidden="true"></i> Edit Sources </button>'
|
sources_button = ' <button class="button iis-info"> <i class="fa fa-cloud-download" aria-hidden="true"></i> Edit Sources </button>'
|
||||||
blends_button = ' <button class="button iis-info"> <i class="fa fa-download" aria-hidden="true"></i> Install a Blend </button>'
|
blends_button = ' <button class="button iis-info"> <i class="fa fa-download" aria-hidden="true"></i> Install a Blend </button>'
|
||||||
bottom_menu = sources_button + blends_button
|
bottom_menu = sources_button + blends_button
|
||||||
|
# Leave out useless buttons until they do more
|
||||||
|
bottom_menu = ''
|
||||||
build_summary()
|
build_summary()
|
||||||
|
|
||||||
return render_template('software.html',
|
return render_template('software.html',
|
||||||
@@ -26,7 +28,8 @@ def webui_software():
|
|||||||
previous_step = previous_step_url,
|
previous_step = previous_step_url,
|
||||||
next_step = next_step_url,
|
next_step = next_step_url,
|
||||||
bottom_menu = bottom_menu,
|
bottom_menu = bottom_menu,
|
||||||
popcon=current_app.config['CONFIG']['recipe']['popcon']['enable_popcon'])
|
popcon=current_app.config['CONFIG']['recipe']['popcon']['enable_popcon'],
|
||||||
|
desktop=current_app.config['CONFIG']['recipe']['install_desktop_environment']['packages'])
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/software/settings', methods=['GET', 'POST'])
|
@bp.route('/software/settings', methods=['GET', 'POST'])
|
||||||
@@ -42,6 +45,19 @@ def software_settings():
|
|||||||
return ('', 204)
|
return ('', 204)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/software/select-desktop', methods=['GET', 'POST'])
|
||||||
|
def software_select_desktop():
|
||||||
|
"""
|
||||||
|
Select a desktop environment for installation
|
||||||
|
"""
|
||||||
|
if request.method == 'POST':
|
||||||
|
desktop = request.form['software-desktop']
|
||||||
|
print(desktop)
|
||||||
|
current_app.config['CONFIG']['recipe']['install_desktop_environment']['packages'] = desktop
|
||||||
|
build_summary()
|
||||||
|
return ('', 204)
|
||||||
|
|
||||||
|
|
||||||
def build_menu():
|
def build_menu():
|
||||||
"""
|
"""
|
||||||
Define menu items and paths.
|
Define menu items and paths.
|
||||||
@@ -58,7 +74,7 @@ def build_summary():
|
|||||||
current_app.config['CONFIG']['Summary']['software'] = {}
|
current_app.config['CONFIG']['Summary']['software'] = {}
|
||||||
current_app.config['CONFIG']['Summary']['software']['heading'] = "Software"
|
current_app.config['CONFIG']['Summary']['software']['heading'] = "Software"
|
||||||
current_app.config['CONFIG']['Summary']['software']['bleh'] = current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']
|
current_app.config['CONFIG']['Summary']['software']['bleh'] = current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']
|
||||||
current_app.config['CONFIG']['Summary']['software']['text'] = "Participate in Popularity Contest: " + str(current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']) + "<br/>No desktop environment selected."
|
current_app.config['CONFIG']['Summary']['software']['text'] = "Participate in Popularity Contest: " + str(current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']) + "<br/>Desktop environment selected: " + str(current_app.config['CONFIG']['recipe']['install_desktop_environment']['packages'])
|
||||||
return("ok?")
|
return("ok?")
|
||||||
|
|
||||||
|
|
||||||
@@ -4,26 +4,45 @@
|
|||||||
<p> <b> Would you like fries with that? </b></p>
|
<p> <b> Would you like fries with that? </b></p>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
<big> Popularity Contest </big>
|
||||||
<div style="background-color: gray; padding: 4px 6px 7px 6px;
|
<br><br>
|
||||||
border-radius: 10px; margin-bottom: 20px;">
|
|
||||||
|
|
||||||
<span style="width: 100%; border-radius: 8px 8px 0 0;"
|
|
||||||
class="tag is-black">
|
|
||||||
Popularity Contest
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div style="padding-left: 15px; padding-right: 15px; background-color: #fff;
|
|
||||||
color: #000;">
|
|
||||||
|
|
||||||
<p>The Popularity Contest (popcon) is a programme where anonymous data is sent back to Debian, tracking the number of packages installed. More information can be obtained at https://popcon.debian.org.</p> <br>
|
<p>The Popularity Contest (popcon) is a programme where anonymous data is sent back to Debian, tracking the number of packages installed. More information can be obtained at https://popcon.debian.org.</p> <br>
|
||||||
|
|
||||||
<input style="background-color: #777777;" type="checkbox" id="popcon"
|
<input style="background-color: #777777;" type="checkbox" id="popcon"
|
||||||
name="popcon" hx-post="/software/settings" hx-trigger="change"
|
name="popcon" hx-post="/software/settings" hx-trigger="change"
|
||||||
{% if popcon %} checked {% endif %}>
|
{% if popcon %} checked {% endif %}>
|
||||||
<label for="popcon"> Participate in PopCon </label><br>
|
<label for="popcon"> Participate in PopCon </label><br>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<big><h3> Desktop Environment </h3></big>
|
||||||
|
<br>
|
||||||
|
<p>Would you like to install a graphical environment for this system?</p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
<div class="control is-link">
|
||||||
|
<div class="select">
|
||||||
|
<select hx-post="/software/select-desktop" hx-target="body" name="software-desktop" style="width: 220px">
|
||||||
|
<option value="" {% if desktop == "None" %} selected=selected {% endif %}> None</option>
|
||||||
|
<option value="task-gnome-desktop" {% if desktop == "task-gnome-desktop" %} selected=selected {% endif %} >GNOME</option>
|
||||||
|
<option value="task-kde-desktop" {% if desktop == "task-kde-desktop" %} selected=selected {% endif %}>KDE Plasma</option>
|
||||||
|
<option value="task-xfce-desktop" {% if desktop == "task-xfce-desktop" %} selected=selected {% endif %}>Xfce</option>
|
||||||
|
<option value="task-lxde-desktop" {% if desktop == "task-lxde-desktop" %} selected=selected {% endif %}>LXDE</option>
|
||||||
|
<option value="task-lxqt-desktop" {% if desktop == "task-lxqt-desktop" %} selected=selected {% endif %}>LXQt</option>
|
||||||
|
<option value="task-mate-desktop" {% if desktop == "task-mate-desktop" %} selected=selected {% endif %}>MATE</option>
|
||||||
|
<option value="lomiri" {% if desktop == "lomiri" %} selected=selected {% endif %}>Lomiri</option>
|
||||||
|
<option value="task-cinnamon-desktop" {% if desktop == "task-cinnamon-desktop" %} selected=selected {% endif %}>Cinnamon</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
<div style="background-color: gray; padding: 4px 6px 7px 6px; border-radius: 10px;">
|
<div style="background-color: gray; padding: 4px 6px 7px 6px; border-radius: 10px;">
|
||||||
<p> <span style="width: 100%; border-radius: 8px 8px 0 0;" class="tag is-black">
|
<p> <span style="width: 100%; border-radius: 8px 8px 0 0;" class="tag is-black">
|
||||||
@@ -56,5 +75,6 @@ Select software from Debian archives</span>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
@@ -3,5 +3,5 @@ from flask import Blueprint
|
|||||||
bp = Blueprint('summary', __name__,
|
bp = Blueprint('summary', __name__,
|
||||||
template_folder='')
|
template_folder='')
|
||||||
|
|
||||||
from applets.summary import routes
|
from yasi_applets.summary import routes
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from applets.summary import bp
|
from yasi_applets.summary import bp
|
||||||
from flask import Flask, request, session, redirect, \
|
from flask import Flask, request, session, redirect, \
|
||||||
url_for, render_template, flash, Blueprint
|
url_for, render_template, flash, Blueprint
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
@@ -19,6 +19,9 @@ def summary_index():
|
|||||||
html = (str(current_app.config['CONFIG']['Summary']['welcome']) + "<br>" + str(current_app.config['CONFIG']['Summary']['software']))
|
html = (str(current_app.config['CONFIG']['Summary']['welcome']) + "<br>" + str(current_app.config['CONFIG']['Summary']['software']))
|
||||||
summary = config['Summary']
|
summary = config['Summary']
|
||||||
|
|
||||||
|
print("Config is: ")
|
||||||
|
print(config)
|
||||||
|
|
||||||
return render_template('summary.html',
|
return render_template('summary.html',
|
||||||
menu=current_app.config['CONFIG']['settings']['menu'],
|
menu=current_app.config['CONFIG']['settings']['menu'],
|
||||||
menu_order=current_app.config['CONFIG']['settings']['menu_order'].split(),
|
menu_order=current_app.config['CONFIG']['settings']['menu_order'].split(),
|
||||||
10
src/yasi_applets/users/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('users', __name__,
|
||||||
|
template_folder='',
|
||||||
|
static_folder='static',
|
||||||
|
static_url_path='/users/static')
|
||||||
|
|
||||||
|
|
||||||
|
from yasi_applets.users import routes
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from applets.software import bp
|
from yasi_applets.software import bp
|
||||||
from flask import Flask, request, session, redirect, \
|
from flask import Flask, request, session, redirect, \
|
||||||
url_for, render_template, flash, Blueprint
|
url_for, render_template, flash, Blueprint
|
||||||
import gettext
|
import gettext
|
||||||
@@ -10,7 +10,7 @@ def set_language(LANG):
|
|||||||
"""
|
"""
|
||||||
Sets language for this applet
|
Sets language for this applet
|
||||||
"""
|
"""
|
||||||
translations = gettext.translation("users", './applets/users/locales',
|
translations = gettext.translation("users", '/usr/share/yasi-daemon/yasi_applets/users/locales',
|
||||||
fallback=True, languages=[LANG])
|
fallback=True, languages=[LANG])
|
||||||
translations.install()
|
translations.install()
|
||||||
_ = translations.gettext
|
_ = translations.gettext
|
||||||
@@ -33,11 +33,12 @@ def users_root():
|
|||||||
else:
|
else:
|
||||||
previous_step_url = menu[menu.index("users")-1]
|
previous_step_url = menu[menu.index("users")-1]
|
||||||
|
|
||||||
root_button = ' <button class="button is-light"> <i class="fa fa-user" aria-hidden="true"></i> Setup root user </button>'
|
root_button = ' <button class="button not-allowed is-light"> <i class="fa fa-user" aria-hidden="true"></i> Setup root user </button>'
|
||||||
ldap_button = ' <button class="button is-light"> <i class="fa fa-address-card" aria-hidden="true"></i> Connect LDAP </button>'
|
ldap_button = ' <button class="button is-light"> <i class="fa fa-address-card" aria-hidden="true"></i> Connect LDAP </button>'
|
||||||
ad_button = ' <button class="button is-light"> <i class="fa fa-address-card" aria-hidden="true"></i> Connect AD </button>'
|
ad_button = ' <button class="button is-light"> <i class="fa fa-address-card" aria-hidden="true"></i> Connect AD </button>'
|
||||||
csv_button = ' <button class="button is-light"> <i class="fa fa-users" aria-hidden="true"></i> Import CSV </button>'
|
csv_button = ' <button class="button is-light"> <i class="fa fa-users" aria-hidden="true"></i> Import CSV </button>'
|
||||||
bottom_menu = root_button + ldap_button + ad_button + csv_button
|
bottom_menu = root_button + ldap_button + ad_button + csv_button
|
||||||
|
bottom_menu = ""
|
||||||
|
|
||||||
initial_user = current_app.config['CONFIG']['recipe']['users']['users'][0]
|
initial_user = current_app.config['CONFIG']['recipe']['users']['users'][0]
|
||||||
|
|
||||||
@@ -55,28 +56,32 @@ def users_root():
|
|||||||
@bp.route('/users/user-check/', methods=['GET', 'POST', 'PUT'])
|
@bp.route('/users/user-check/', methods=['GET', 'POST', 'PUT'])
|
||||||
def check_user():
|
def check_user():
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
print("Ok, so method is POST")
|
|
||||||
print("keys are: ", request.form.keys())
|
|
||||||
username = request.form["username"]
|
username = request.form["username"]
|
||||||
fullname = request.form["fullname"]
|
fullname = request.form["fullname"]
|
||||||
password = request.form["password"]
|
|
||||||
password_confirm = request.form["password_confirm"]
|
|
||||||
print(current_app.config['CONFIG']['recipe']['users']['users'][0])
|
|
||||||
print("fullname is: " + fullname)
|
|
||||||
print("password is: " + password)
|
|
||||||
print("password_confirm is: " + password_confirm)
|
|
||||||
current_app.config['CONFIG']['recipe']['users']['users'][0]['username'] = username
|
current_app.config['CONFIG']['recipe']['users']['users'][0]['username'] = username
|
||||||
current_app.config['CONFIG']['recipe']['users']['users'][0]['fullname'] = fullname
|
current_app.config['CONFIG']['recipe']['users']['users'][0]['fullname'] = fullname
|
||||||
current_app.config['CONFIG']['recipe']['users']['users'][0]['password'] = password
|
|
||||||
current_app.config['CONFIG']['recipe']['users']['users'][0]['password_confirm'] = password_confirm
|
|
||||||
if username in ["root", "games"]:
|
if username in ["root", "games"]:
|
||||||
return('<p class="has-text-danger"><b>That username is not available</b> </p>')
|
return('<p class="has-text-danger"><b>That username is not available</b> </p>')
|
||||||
else:
|
else:
|
||||||
return('<p class="has-text-success"><b>That username is available</b> </p>')
|
return('<p class="has-text-success"><b>That username is available</b> </p>')
|
||||||
build_summary()
|
build_summary()
|
||||||
return("bleh")
|
return("")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/users/password-check/', methods=['GET', 'POST', 'PUT'])
|
||||||
|
def check_password():
|
||||||
|
if request.method == 'POST':
|
||||||
|
password = request.form["password"]
|
||||||
|
password_confirm = request.form["password_confirm"]
|
||||||
|
current_app.config['CONFIG']['recipe']['users']['users'][0]['password'] = password
|
||||||
|
current_app.config['CONFIG']['recipe']['users']['users'][0]['password_confirm'] = password_confirm
|
||||||
|
if password != password_confirm:
|
||||||
|
return('<p class="has-text-danger"><b>Passwords do not match</b> </p>')
|
||||||
|
else:
|
||||||
|
return('<p class="has-text-success"><b>Passwords match</b> </p>')
|
||||||
|
build_summary()
|
||||||
|
return("")
|
||||||
|
|
||||||
|
|
||||||
def build_stringlist():
|
def build_stringlist():
|
||||||
"""
|
"""
|
||||||
@@ -96,6 +101,8 @@ def build_stringlist():
|
|||||||
string_dict['password_confirm'] = _("Password (confirm)")
|
string_dict['password_confirm'] = _("Password (confirm)")
|
||||||
string_dict['password_nomatch'] = _("These passwords do now match")
|
string_dict['password_nomatch'] = _("These passwords do now match")
|
||||||
string_dict['password_tooshort'] = _("This password is too short")
|
string_dict['password_tooshort'] = _("This password is too short")
|
||||||
|
string_dict['next_text'] = _("Next")
|
||||||
|
string_dict['back_text'] = _("Back")
|
||||||
return string_dict
|
return string_dict
|
||||||
|
|
||||||
|
|
||||||
@@ -104,7 +111,6 @@ def build_menu():
|
|||||||
Define menu items and paths.
|
Define menu items and paths.
|
||||||
"""
|
"""
|
||||||
current_app.config['CONFIG']['settings']['menu']['users'] = (build_stringlist()['menu_item'], "/users", 20)
|
current_app.config['CONFIG']['settings']['menu']['users'] = (build_stringlist()['menu_item'], "/users", 20)
|
||||||
print(current_app.config['CONFIG']['settings']['menu'])
|
|
||||||
|
|
||||||
|
|
||||||
def build_summary():
|
def build_summary():
|
||||||
@@ -113,7 +119,6 @@ def build_summary():
|
|||||||
"""
|
"""
|
||||||
current_app.config['CONFIG']['Summary']['users'] = {}
|
current_app.config['CONFIG']['Summary']['users'] = {}
|
||||||
current_app.config['CONFIG']['Summary']['users']['heading'] = "Users and Identity"
|
current_app.config['CONFIG']['Summary']['users']['heading'] = "Users and Identity"
|
||||||
current_app.config['CONFIG']['Summary']['users']['bleh'] = current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']
|
|
||||||
current_app.config['CONFIG']['Summary']['users']['settings'] = current_app.config['CONFIG']['recipe']['users']['users']
|
current_app.config['CONFIG']['Summary']['users']['settings'] = current_app.config['CONFIG']['recipe']['users']['users']
|
||||||
current_app.config['CONFIG']['Summary']['users']['text'] = "Add primary user with the username: " + str(current_app.config['CONFIG']['recipe']['users']['users'][0]['username'])
|
current_app.config['CONFIG']['Summary']['users']['text'] = "Add primary user with the username: " + str(current_app.config['CONFIG']['recipe']['users']['users'][0]['username'])
|
||||||
return("ok?")
|
return("ok?")
|
||||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<form action="/users" method="POST">
|
<form action="/users" method="POST">
|
||||||
|
|
||||||
<img src="/static/icons/avatar-default.svg" width="160px" style="float: left; position: absolute;" />
|
<img src="/users/static/img/avatar-default.svg" width="160px" style="float: left; position: absolute;" />
|
||||||
|
|
||||||
<div style="margin-left: 180px;">
|
<div style="margin-left: 180px;">
|
||||||
|
|
||||||
@@ -18,16 +18,22 @@
|
|||||||
<span class="icon is-small is-left">
|
<span class="icon is-small is-left">
|
||||||
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
|
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
|
<!-- <span class="icon is-small is-right">
|
||||||
|
<img src="/static/icons/emblem-default-symbolic.svg">
|
||||||
|
</span> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{ string_dict['user_name'] }}</label>
|
<label>{{ string_dict['user_name'] }}</label>
|
||||||
<div class="control has-icons-left has-icons-right">
|
<div class="control has-icons-left has-icons-right">
|
||||||
<input class="input is-success" type="text" placeholder="{{ string_dict['user_name'] }}" value="{% if initial_user['username'] %}{{ initial_user['username'] }}{% endif %}" name="username" hx-post="/users/user-check" hx-trigger="keyup changed delay:200ms" hx-trigger="load" hx-target="#username-status">
|
<input class="input" type="text" placeholder="{{ string_dict['user_name'] }}" value="{% if initial_user['username'] %}{{ initial_user['username'] }}{% endif %}" name="username" hx-post="/users/user-check" hx-trigger="keyup changed delay:200ms" hx-trigger="load" hx-target="#username-status">
|
||||||
<span class="icon is-small is-left">
|
<span class="icon is-small is-left">
|
||||||
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
|
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
|
<!-- <span class="icon is-small is-right">
|
||||||
|
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
|
||||||
|
</span> -->
|
||||||
</div>
|
</div>
|
||||||
<div id="username-status">
|
<div id="username-status">
|
||||||
<p> {{ string_dict['user_name_hint'] }}</p>
|
<p> {{ string_dict['user_name_hint'] }}</p>
|
||||||
@@ -37,7 +43,7 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="password">{{ string_dict['password'] }}</label>
|
<label class="password">{{ string_dict['password'] }}</label>
|
||||||
<div class="control has-icons-left has-icons-right">
|
<div class="control has-icons-left has-icons-right">
|
||||||
<input class="input" name="password" type="password" placeholder="{{ string_dict['password'] }}" value="{% if initial_user['password'] %}{{ initial_user['password'] }}{% endif %}" hx-post="/users/user-check" hx-trigger="keyup changed delay:200ms" hx-target="#username-status">
|
<input class="input" name="password" type="password" placeholder="{{ string_dict['password'] }}" value="{% if initial_user['password'] %}{{ initial_user['password'] }}{% endif %}" hx-post="/users/password-check" hx-trigger="keyup changed delay:200ms" hx-target="#password-status">
|
||||||
<span class="icon is-small is-left">
|
<span class="icon is-small is-left">
|
||||||
<i class="fa fa-address-card" aria-hidden="true"></i>
|
<i class="fa fa-address-card" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
@@ -47,10 +53,13 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="password">{{ string_dict['password_confirm'] }}</label>
|
<label class="password">{{ string_dict['password_confirm'] }}</label>
|
||||||
<div class="control has-icons-left has-icons-right">
|
<div class="control has-icons-left has-icons-right">
|
||||||
<input class="input" name="password_confirm" type="password" placeholder="{{ string_dict['password_confirm'] }}" value="{% if initial_user['password_confirm'] %}{{ initial_user['password_confirm'] }}{% endif %}" hx-post="/users/user-check" hx-trigger="keyup changed delay:200ms" hx-target="#password-status">
|
<input class="input" name="password_confirm" type="password" placeholder="{{ string_dict['password_confirm'] }}" value="{% if initial_user['password_confirm'] %}{{ initial_user['password_confirm'] }}{% endif %}" hx-post="/users/password-check" hx-trigger="keyup changed delay:200ms" hx-target="#password-status">
|
||||||
<span class="icon is-small is-left">
|
<span class="icon is-small is-left">
|
||||||
<i class="fa fa-address-card" aria-hidden="true"></i>
|
<i class="fa fa-address-card" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
|
<div id="password-status">
|
||||||
|
<p> </p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
8
src/yasi_applets/welcome/__init__.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
bp = Blueprint('welcome', __name__,
|
||||||
|
template_folder='',
|
||||||
|
static_folder='static',
|
||||||
|
static_url_path='/welcome/static')
|
||||||
|
|
||||||
|
from yasi_applets.welcome import routes
|
||||||
BIN
src/yasi_applets/welcome/locales/af/LC_MESSAGES/welcome.mo
Normal file
@@ -12,6 +12,33 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: UTF-8\n"
|
"Content-Transfer-Encoding: UTF-8\n"
|
||||||
|
|
||||||
|
msgid "Welcome"
|
||||||
|
msgstr "Welkom"
|
||||||
|
|
||||||
|
msgid "Users"
|
||||||
|
msgstr "Gebruikers"
|
||||||
|
|
||||||
|
msgid "Disks"
|
||||||
|
msgstr "Skywe"
|
||||||
|
|
||||||
|
msgid "Software"
|
||||||
|
msgstr "Sagteware"
|
||||||
|
|
||||||
|
msgid "Summary"
|
||||||
|
msgstr "Opsomming"
|
||||||
|
|
||||||
|
msgid "Power"
|
||||||
|
msgstr "Krag"
|
||||||
|
|
||||||
|
msgid "Internet"
|
||||||
|
msgstr "Internet"
|
||||||
|
|
||||||
|
msgid "Back"
|
||||||
|
msgstr "Terug"
|
||||||
|
|
||||||
|
msgid "Next"
|
||||||
|
msgstr "Volgende"
|
||||||
|
|
||||||
#: routes.py:27
|
#: routes.py:27
|
||||||
msgid "Welcome! This setup program will install Debian on to your system."
|
msgid "Welcome! This setup program will install Debian on to your system."
|
||||||
msgstr "Welkom! Hierdie program sal jou deur die proses lei om Debian te installeer na jou sisteem."
|
msgstr "Welkom! Hierdie program sal jou deur die proses lei om Debian te installeer na jou sisteem."
|
||||||