Compare commits

29 Commits

Author SHA1 Message Date
Jonathan Carter
de76cd16ea Commit recent changes 2026-03-14 15:14:37 +02:00
Jonathan Carter
24c5f6e12d Add erase confirm screen 2026-03-10 15:43:34 +02:00
Jonathan Carter
3a3d211cd3 Commit previous changes 2026-03-10 15:43:14 +02:00
Jonathan Carter
829149ebc1 Improve app frame buttons 2026-02-16 19:06:32 +02:00
Jonathan Carter
87799719c2 Add images and gitignore 2026-02-04 09:09:00 +02:00
Jonathan Carter
401bfb55d9 some disks refactoring 2026-01-14 13:47:36 +02:00
Jonathan Carter
1c4656ade3 merge 2026-01-12 12:21:46 +02:00
Jonathan Carter
7337daac01 Submit local changes 2026-01-12 12:20:15 +02:00
Jonathan Carter
7eec15b7df Some partition ui stuff 2026-01-11 21:19:29 +02:00
Jonathan Carter
d823bdd251 Set window height 2026-01-07 22:37:48 +02:00
Jonathan Carter
f10ff43adb Rework partition page a bit 2026-01-07 22:29:22 +02:00
Jonathan Carter
ed2ddb0a77 list debian deps 2025-12-10 21:18:21 +02:00
Jonathan Carter
31bb032a4e Set text_select to false for new pywbview' 2025-10-25 21:52:17 +02:00
Jonathan Carter
22dcf36b14 cleanup mainapplet a bit 2025-08-31 18:31:51 +02:00
Jonathan Carter
088bf495f5 Bunch of ui stuff 2025-08-31 14:53:40 +02:00
Jonathan Carter
c0aa82241b Fix static scrolling 2025-08-28 12:26:13 +02:00
Jonathan Carter
9544463bd6 Minor changes 2025-08-26 16:07:34 +02:00
Jonathan Carter
60cd5140d2 Add systemd unit 2025-08-26 15:58:42 +02:00
Jonathan Carter
dcbc8dd062 Try to make header moving work 2025-08-26 15:58:32 +02:00
Jonathan Carter
08f232bf51 Rename to yasi, add icon 2025-08-26 15:22:26 +02:00
Jonathan Carter
75d068fef6 Exclude cd and loop devs 2025-08-25 20:58:26 +02:00
Jonathan Carter
373ce1247e More cleanup 2025-08-23 23:59:50 +02:00
Jonathan Carter
eaa983e955 Fix extension 2025-08-23 22:59:18 +02:00
Jonathan Carter
652bbba9c0 re-add yasi-applets 2025-08-23 22:33:58 +02:00
Jonathan Carter
69d6ba277d Move a whole bunch of stuff around 2025-08-23 22:33:41 +02:00
Jonathan Carter
8791c58cbf Various ui work 2025-08-23 16:03:38 +02:00
Jonathan Carter
258a359ce1 commit some failed experiments 2025-08-19 20:28:02 +02:00
Jonathan Carter
21b210a689 Some more UI work 2025-08-18 23:08:51 +02:00
Jonathan Carter
430b144d92 Add installer slide placeholder 2025-08-16 14:23:29 +02:00
125 changed files with 1374 additions and 701 deletions

View File

@@ -10,12 +10,18 @@ Dependencies:
- flask
- pytest
- coverage
- libxapp-gtk3-module
- gettext
Recommended:
- 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)
- 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

2
src/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
__pycache__
.swp

View File

@@ -1,7 +0,0 @@
from flask import Blueprint
bp = Blueprint('disks', __name__,
template_folder='')
from applets.disks import routes

View File

@@ -1,65 +0,0 @@
from applets.disks import bp
from flask import Flask, request, session, redirect, \
url_for, render_template, flash, Blueprint
import dmm.lsblk as lsblk
from flask import current_app
@bp.route('/disks')
def disks():
"""
Disks screen for the webui.
"""
blockdevs = lsblk.list_block_devices()
print(lsblk.list_block_devices())
menu = current_app.config['CONFIG']['settings']['menu_order'].split(" ")
next_step_url = menu[menu.index("disks")+1]
if menu[menu.index("disks")] == 1:
previous_step_url = False
else:
previous_step_url = menu[menu.index("disks")-1]
add_disks_button = '&nbsp; <button class="button iis-info"> <i class="fa fa-hdd-o" aria-hidden="true"></i> &nbsp; Add Disk or Filesystem </button>'
add_swap_button = '&nbsp; <button class="button iis-info"> <i class="fa fa-object-group" aria-hidden="true"></i> &nbsp; Swap Configuration </button>'
bottom_menu = add_disks_button + add_swap_button
build_summary()
return render_template('disks.html', blockdevs=blockdevs,
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)
@bp.route('/disks/partition/<part>')
def disks_partition(part):
"""
Partition modal for the webui partition screen.
"""
print("Partition is: " + part)
partition = part
return render_template('disks_partition.html',
menu=current_app.config['CONFIG']['settings']['menu'],
partition=partition)
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']['disks'] = ("Disks", "/disks", 30)
def build_summary():
"""
Write up a summary of what this module will do.
"""
current_app.config['CONFIG']['Summary']['disks'] = {}
current_app.config['CONFIG']['Summary']['disks']['heading'] = "Disks and Partitions"
current_app.config['CONFIG']['Summary']['disks']['bleh'] = current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']
current_app.config['CONFIG']['Summary']['disks']['text'] = "Pre-configured disk layout."
return("ok?")
build_menu()

View File

@@ -1,7 +0,0 @@
from flask import Blueprint
bp = Blueprint('install', __name__,
template_folder='')
from applets.install import routes

View File

@@ -1,7 +0,0 @@
from flask import Blueprint
bp = Blueprint('main', __name__,
template_folder='')
from applets.main import routes

View File

@@ -1,7 +0,0 @@
from flask import Blueprint
bp = Blueprint('software', __name__,
template_folder='')
from applets.software import routes

View File

@@ -1,7 +0,0 @@
from flask import Blueprint
bp = Blueprint('users', __name__,
template_folder='')
from applets.users import routes

View File

@@ -1,6 +0,0 @@
from flask import Blueprint
bp = Blueprint('webui', __name__)
from applets.webui import routes

View File

@@ -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')

View File

@@ -1,6 +0,0 @@
from flask import Blueprint
bp = Blueprint('welcome', __name__,
template_folder='')
from applets.welcome import routes

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -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"> &nbsp; Power: AC </button>'
internet_button = '&nbsp; <button class="button is-dark"> <img width="16px;" src="/static/icons/greencheck.png"> &nbsp; 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

View File

@@ -1,58 +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-o" 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 %}

View File

@@ -1 +0,0 @@
../../../applets/welcome/img

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -1,30 +0,0 @@
<!-- 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. -->
<a href="/{{ previous_step }}"><button hx-get="/{{ previous_step }}" hx-target="body" hx-trigger="click, keyup[ctrlKey&&code=='PageUp'] from:body" class="button is-light">Back</button></a>
<a href="/{{ previous_step }}"><button hx-get="/{{ previous_step }}" hx-target="body" hx-trigger="click, keyup[altKey&&key=='b'] from:body" class=""></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-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, keyup[ctrlKey&&code=='PageDown'] from:body" class=""></button></a>
<a href="/{{ next_step }}"<button hx-get="/{{ next_step }}" hx-target="body" hx-trigger="click, keyup[altKey&&key=='n'] from:body" class="button is-link">Next</button></a>
{% endif %}
{% endif %}
</div>

View File

@@ -1,21 +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;"> -->
<a hx-get="/main/menu" hx-swap="outerHTML"/> <button class="button is-link"></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"> <b> ? </b> </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 -->

View File

@@ -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>

View File

@@ -1,6 +1,6 @@
#!/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, \
@@ -10,10 +10,10 @@ import logging
import dmm.lsblk as lsblk
import importlib
import yaml
import sys
# configuration
#CONFIGFILE="templates/dmm-installer-template.yaml"
CONFIGFILE="templates/dmm-installer-vm-template.yaml"
CONFIGFILE="/etc/yasi/yasi.yaml"
# import config
global config
@@ -28,6 +28,7 @@ app.config.from_object(__name__)
app.config['CONFIG'] = config
app.app_context().push()
config['settings']['menu'] = {}
sys.path.append('/usr/share/yasi-daemon')
if DEV_MODE:
print("Note: Starting in devmode!")
@@ -38,7 +39,7 @@ if DEV_MODE:
for APP in APPS.split(" "):
print(f"Loading applet: {APP} ")
# 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
bp = getattr(module, "bp")
# Register the blueprint with the app
@@ -53,8 +54,8 @@ if DEV_MODE == "1":
if __name__ == '__main__':
serve(app,
host='0.0.0.0',
port=8080,
host='127.0.0.1',
port=9274,
url_scheme='http',
expose_tracebacks=DEV_MODE)

50
src/yasi-webclient Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python3
import webview
LOCATION = "http://localhost:9274/welcome"
class Api():
def log(self, value):
print(value)
def close(self):
window.destroy()
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, height=650, focus=True, zoomable=True,
confirm_close=False, resizable=True, shadow=True,
text_select=False, draggable=True, js_api=Api()
)
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
}
def custom_logic(window):
pass
#window.toggle_fullscreen()
#window.evaluate_js('alert("Nice one brother")')
#window.destroy()
window.events.closed += on_closed
#webview.start(icon='/usr/share/icons/yasi.png')
webview.start(custom_logic, window)

View File

View File

@@ -0,0 +1,9 @@
from flask import Blueprint
bp = Blueprint('disks', __name__,
template_folder='',
static_folder='static',
static_url_path='/disks/static')
from yasi_applets.disks import routes

View File

@@ -1,34 +1,7 @@
{% extends "layout.html" %}
{% block body %}
<div style="">
<p><b>How would you like to install Debian?</b></p>
<br>
<div class="radios">
<label class="radio">
<input type="radio" name="rsvp" />
Preconfigured partitioning &nbsp;
<label class="radio">
<input type="radio" name="rsvp" disabled />
Erase entire disk
</label>
<label class="radio">
<input type="radio" name="rsvp" disabled />
Install alongside another operating system
</label>
<label class="radio">
<input type="radio" name="rsvp" disabled />
Edit existing partitions
</label>
</div>
<div class="columns" width="100%">
<div class="column"><p> <br>Proposed layout: </p></div>
</div>
<!--
<div style="">
<div style="background-color: gray; padding: 4px 6px 7px 6px; border-radius: 10px;">
@@ -64,10 +37,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>
{{ disk }}
@@ -87,33 +59,57 @@ fssize: {{ child['fssize'] }}
<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>{{ disk['name'] }} ({{(disk['size']/1024000000)|round(0)|int }} GB) - Serial: {{ disk['serial'] }}</small></small>
<div class="columns">
{% for child in disk['children'] %}
<a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML"/>
<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">{{ child['name'] }} ({{ (child['size']/1024000000)|round(2) }} GiB) </p>
<p class="title is-5"><span class="tag is-black">{{ child['mountpoint'] }}</span>
<span class="tag is-link">{{ child['fstype'] }}</span>
</p>
</div>
</div>
</a>
{% endfor %}
<b>{{ disk['name'] }}: &nbsp; </b> {{ disk['model'] }} - {{ disk['tran'] }} disk ({{(disk['size']/1024000000)|round(0)|int }} GB) - Serial: {{ disk['serial'] }} </p>
<center style="padding: 5px; padding-bottom: 5px;">
<td><a hx-get="/disks/details/{{ disk['name'] }}" hx-swap="outerHTML"><span class="tag is-link"> Disk Details </span></a></td>
<td><a hx-get="/disks/wipe_table/{{ disk['name'] }}" hx-swap="outerHTML"><span class="tag is-link"> Wipe Disk </span></a></td>
<td><a hx-get="/disks/new_partition/{{ disk['name'] }}" hx-swap="outerHTML"><span class="tag is-link"> New Partition </span></a></td>
<td><a hx-get="/disks/replicate/{{ disk['name'] }}" hx-swap="outerHTML"><span class="tag is-link"> Replicate Layout </span></a></td>
<td><a hx-get="/disks/diagnostics/{{ disk['name'] }}" hx-swap="outerHTML"><span class="tag is-link"> Diagnostics </span></a></td>
</center>
{% if disk['maj:min'] == "252:0" %}
<div class="column is-narrow is-primary">
<div class="column">
<div class="box" style="width: 100%; border-radius: 0 0 0px 5px; height: 60px; padding-top: 5px; right: 0px;">
<p class="is-tiny"> {{ disk['name'] }} ({{ (disk['size']/1024000000)|round(2) }} GiB) </p>
<p class="title is-5"><span class="tag is-black">/dev/{{ disk['name'] }}</span>
<span class="tag is-link">swap</span>
</p>
</div>
</div>
{% endif %}
{% set colors = ['teal', '#E69F00', '#56B4E9', '#009E73', '#0072B2', '#D55E00', '#CC79A7'] %}
<div id="percentagebar" style="width: 100%; height: 50px; background-color: transparent; display: inline-block; margin: 5; padding: 5; overflow: hidden; display: flex;">
{% for child in disk['children'] %}
<a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML">
<div style="min-width: 100px; width: {{ (((child['size'] / disk['size'])*100)|round(0)|int) }}%; height: 100%; background-color: {{ colors[loop.index0 % colors|length] }}; display: inline-block; margin: 1; padding: 1; border-radius: 8px;">
&nbsp; <a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML"> <font color="white">{{ child['name'] }} </font>
</div></a>
{% endfor %}
</div>
<table width="100%">
<th>Partition</th>
<th>Type</th>
<th>Mount Point</th>
<th>Label</th>
<th>Size</th>
<th>Used</th>
{% for child in disk['children'] %}
<tr>
<td><a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML"><span class="tag is-link">{{ child['name'] }}</span></a></td>
<td>{{ child['fstype'] }}</td>
<td>{{ child['mountpoint'] }}</td>
<td>{{ child['label'] }} </td>
<td>{{ (child['size']/1024000000)|round(2) }} GiB </td>
</tr>
{% endfor %}
</table>
</div>
</div>
<br />
<!--
<p> Diskname: {{ disk['name'] }} </p>
<p> Model: {{ disk['model'] }} </p>
@@ -127,6 +123,7 @@ fssize: {{ child['fssize'] }}
<p> There are {{ disk['children']|count }} Children </p>
-->
<!--
{% for child in disk['children'] %}
<br>
@@ -137,17 +134,40 @@ fssize: {{ child['fssize'] }}
{% endfor %}
-->
<br>
{% endfor %}
<!-- Add Undetected Disk
Add Virtual 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>

View File

@@ -0,0 +1,40 @@
<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"> Disk: {{ disk }} </h1>
<p>
{% for pdisk in blockdevs["blockdevices"] if pdisk["name"] != "zram0" and "loop" not in pdisk["name"] and pdisk["name"] != "sr0" %}
{% if pdisk['name'] == disk %}
<p> Model: {{ pdisk['model'] }} </p>
<p> Revision: {{ pdisk['rev'] }} </p>
<p> Serial: {{ pdisk['serial'] }} </p>
<p> Link: {{ pdisk['id-link'] }} </p>
<p> Path: {{ pdisk['path'] }} </p>
<p> Label: {{ pdisk['label'] }} </p>
<p> Partition type: {{ pdisk['pttype'] }} </p>
<p> Interface: {{ pdisk['tran'] }} </p>
<p> Size: {{ pdisk['size'] }} </p>
<p> Flags: {{ pdisk['flags'] }} </p>
<p> UUID: {{ pdisk['uuid'] }} </p>
<p> Partitions: {{ pdisk['children']|count }} </p>
{% endif %}
{% endfor %}
</p>
<div class="columns">
<a href="/disks">
<div class="column"><button class="button is-light">Cancel</button></div>
</a>
<a href="/disks"><div class="column"><button class="button is-link">Continue</button></div></a>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,105 @@
{% extends "layout.html" %}
{% block body %}
<p><b>The following disk will be erased:</b></p>
{% for disk in blockdevs["blockdevices"] if disk["name"] == diskname %}
{% set disk_size = disk['size'] %}
<div style="padding-top: 20px;"> <!-- 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">
<b>{{ disk['name'] }}: &nbsp; </b> {{ disk['model'] }} - {{ disk['tran'] }} disk ({{(disk['size']/1024000000)|round(0)|int }} GB) - Serial: {{ disk['serial'] }} </p>
<center style="padding: 5px; padding-bottom: 5px;">
</center>
{% if disk['maj:min'] == "252:0" %}
<div class="column">
<div class="box" style="width: 100%; border-radius: 0 0 0px 5px; height: 60px; padding-top: 5px; right: 0px;">
<span class="tag is-link">swap</span>
</p>
</div>
</div>
{% endif %}
{% set colors = ['teal', '#E69F00', '#56B4E9', '#009E73', '#0072B2', '#D55E00', '#CC79A7'] %}
<div id="percentagebar" style="width: 100%; height: 50px; background-color: transparent; display: inline-block; margin: 5; padding: 5; overflow: hidden; display: flex;">
{% for child in disk['children'] %}
<a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML">
<div style="min-width: 100px; width: {{ (((child['size'] / disk['size'])*100)|round(0)|int) }}%; height: 100%; background-color: {{ colors[loop.index0 % colors|length] }}; display: inline-block; margin: 1; padding: 1; border-radius: 8px;">
&nbsp; <a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML"> <font color="white">{{ child['name'] }} </font>
</div></a>
{% endfor %}
</div>
<table width="100%">
<th>Partition</th>
<th>Type</th>
<th>Mount Point</th>
<th>Label</th>
<th>Size</th>
{% for child in disk['children'] %}
<tr>
<td><a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML"><span class="tag is-link">{{ child['name'] }}</span></a></td>
<td>{{ child['fstype'] }}</td>
<td>{{ child['mountpoint'] }}</td>
<td>{{ child['label'] }} </td>
<td>{{ (child['size']/1024000000)|round(2) }} GiB </td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
<br>
<p><b>This layout will be created:</b></p>
{% for disk in blockdevs["blockdevices"] if disk["name"] == diskname %}
{% set disk_size = disk['size'] %}
<div style="padding-top: 20px;"> <!-- 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">
<b>New GPT Partition Table on {{ disk['name'] }} </b> </p>
<!-- TODO: Unhardcode that, it might be a BIOS or other type of partition -->
<center style="padding: 5px; padding-bottom: 5px;">
</center>
{% set colors = ['teal', '#E69F00', '#56B4E9', '#009E73', '#0072B2', '#D55E00', '#CC79A7'] %}
<div id="percentagebar" style="width: 100%; height: 50px; background-color: transparent; display: inline-block; margin: 5; padding: 5; overflow: hidden; display: flex;">
{% for partition in partitions['command_set'] if partition['action-type'] == 'newpart' %}
<a hx-get="/disks/partition/" hx-swap="outerHTML">
<div style="min-width: 100px; width: {{ partition['size']}}; display: inline-block; margin: 1; padding: 1; border-radius: 8px; background-color: {{ colors[loop.index0 % colors|length] }}; display: inline-block; margin: 1; padding: 1; border-radius: 8px;">
<!-- TODO: That is totally wrong, but works for POC -->
&nbsp; <a hx-get="/disks/partition/" hx-swap="outerHTML"> <font color="white"> {{ partition['device'] }} </font>
</div></a>
{% endfor %}
</div>
<table width="100%">
<th>Partition</th>
<th>Type</th>
<th>Mount Point</th>
<th>Label</th>
<th>Size</th>
{% for partition in partitions['command_set'] if partition['action-type'] == 'newpart' %}
<tr>
<td><a hx-get="/disks/partition/{{ partition['device']}}" hx-swap="outerHTML"><span class="tag is-link">{{ partition['device'] }}</span></a></td>
<td>{{ partition['fstype'] }}</td>
<td>{{ partition['mountpoint'] }}</td>
<td>{{ partition['label'] }} </td>
<td>{{ partition['size'] }} </td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
<BR>
{% endblock %}

View File

@@ -0,0 +1,58 @@
{% extends "layout.html" %}
{% block body %}
<p><b>Please confirm the disk to erase:</b></p>
{% for disk in blockdevs["blockdevices"] if disk["name"] != "zram0" and "loop" not in disk["name"] and disk["name"] != "sr0" %}
<div style="padding-top: 20px;"> <!-- 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">
<b>{{ disk['name'] }}: &nbsp; </b> {{ disk['model'] }} - {{ disk['tran'] }} disk ({{(disk['size']/1024000000)|round(0)|int }} GB) - Serial: {{ disk['serial'] }} </p>
<center style="padding: 5px; padding-bottom: 5px;">
<td><a href="/disks/choose_disk_erase_chosen/{{ disk['name'] }}"><span class="tag is-link"> Select Disk </span></a></td>
</center>
{% if disk['maj:min'] == "252:0" %}
<div class="column">
<div class="box" style="width: 100%; border-radius: 0 0 0px 5px; height: 60px; padding-top: 5px; right: 0px;">
<span class="tag is-link">swap</span>
</p>
</div>
</div>
{% endif %}
{% set colors = ['teal', '#E69F00', '#56B4E9', '#009E73', '#0072B2', '#D55E00', '#CC79A7'] %}
<div id="percentagebar" style="width: 100%; height: 50px; background-color: transparent; display: inline-block; margin: 5; padding: 5; overflow: hidden; display: flex;">
{% for child in disk['children'] %}
<a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML">
<div style="min-width: 100px; width: {{ (((child['size'] / disk['size'])*100)|round(0)|int) }}%; height: 100%; background-color: {{ colors[loop.index0 % colors|length] }}; display: inline-block; margin: 1; padding: 1; border-radius: 8px;">
&nbsp; <a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML"> <font color="white">{{ child['name'] }} </font>
</div></a>
{% endfor %}
</div>
<table width="100%">
<th>Partition</th>
<th>Type</th>
<th>Mount Point</th>
<th>Label</th>
<th>Size</th>
<th>Used</th>
{% for child in disk['children'] %}
<tr>
<td><a hx-get="/disks/partition/{{ child['name'] }}" hx-swap="outerHTML"><span class="tag is-link">{{ child['name'] }}</span></a></td>
<td>{{ child['fstype'] }}</td>
<td>{{ child['mountpoint'] }}</td>
<td>{{ child['label'] }} </td>
<td>{{ (child['size']/1024000000)|round(2) }} GiB </td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endfor %}
{% endblock %}

View File

@@ -11,12 +11,11 @@
<div class="select">
<select>
<option>Local file system</option>
<option>Remote file system</option>
<option>Logical volume for ZFS zpool</option>
<option>Logical volume for LVM</option>
<option>Logical volume for LUKS encryption</option>
<option>Logical volume for Linux (mdadm) RAID</option>
<option>Logical volume for Microsoft LDM RAID</option>
<option>Logical volume for (existing) Microsoft LDM RAID</option>
<option>Swap partition</option>
<option>Do not configure</option>
</select>
@@ -49,9 +48,6 @@
<option>jfs</option>
<option>ntfs</option>
<option>vfat</option>
<option>nfs</option>
<option>nbd</option>
<option>samba</option>
</select>
</div>
</div>

View File

@@ -0,0 +1,60 @@
{% extends "layout.html" %}
{% block body %}
<p><b>How would you like to install Debian?</b></p>
<br>
<center>
<a href="">
<div style="width: 200px; float: left; padding: 10px; color: white;">
<img width="130px;" src="/disks/static/img/install_alongside.png"><br>
Install next to existing partition
</div>
</a>
<a href="/disks/choose_partition_erase">
<div style="width: 200px; float: left; padding: 10px; color: white;">
<img width="130px;" src="/disks/static/img/erase_partition.png"><br>
Replace a partition
</div>
</a>
<a href="/disks/choose_disk_erase">
<div style="width: 200px; float: left; padding: 10px; color: white;">
<img width="130px;" src="/disks/static/img/erase_disk.png"><br>
Erase entire disk
</div>
</a>
<a href="/disks/advanced">
<div style="width: 200px; float: left; padding: 10px; color: white;">
<img width="130px;" src="/disks/static/img/advanced_partitioning.png"><br>
Advanced partitioning
</div>
</a>
<a href="">
<div style="width: 200px; float: left; padding: 10px; color: white;">
<img width="130px;" src="/disks/static/img/preconfigured_partitioning.png"><br>
Preconfigured Partitioning
</div>
</a>
</center>
<div style="float: none;">
<p> <b>The following devices have been detected:</b>
<br><br>
<ul>
{% for disk in blockdevs["blockdevices"] if disk["name"] != "zram0" and "loop" not in disk["name"] and disk["name"] != "sr0" %}
<li>{{ disk['name'] }}
{% endfor %}
</ul>
{% endblock %}
</div>

View 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"> Wipe partition: {{ disk }} </h1>
<p>Warning: wiping the partition table effectively destroys all data on the disk.</p>
<p>What kind of partition would you like to create? </p>
<p>DOS/MBR (Only use for legacy purposes, disks smaller than 2TB</p>
<p>GPT (Usable on all disk sizes, modern systems)</p>
<div class="columns">
<a href="/disks">
<div class="column"><button class="button is-light">Cancel</button></div>
</a>
<a href="/disks"><div class="column"><button class="button is-link">Continue</button></div></a>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,164 @@
from yasi_applets.disks import bp
from flask import Flask, request, session, redirect, \
url_for, render_template, flash, Blueprint
import dmm.lsblk as lsblk
from flask import current_app
@bp.route('/disks')
def disks_welcome():
"""
Welcome menu for partitioning
"""
menu = current_app.config['CONFIG']['settings']['menu_order'].split(" ")
next_step_url = menu[menu.index("disks")+1]
if menu[menu.index("disks")] == 1:
previous_step_url = False
else:
previous_step_url = menu[menu.index("disks")-1]
blockdevs = lsblk.list_block_devices()
return render_template('disks_welcome.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, blockdevs=blockdevs
)
@bp.route('/disks/choose_disk_erase')
def disks_choose_disk_erase():
"""
Choose a disk to erase
"""
menu = current_app.config['CONFIG']['settings']['menu_order'].split(" ")
next_step_url = menu[menu.index("disks")+1]
if menu[menu.index("disks")] == 1:
previous_step_url = False
else:
previous_step_url = menu[menu.index("disks")-1]
blockdevs = lsblk.list_block_devices()
return render_template('disks_erase_menu.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, blockdevs=blockdevs
)
@bp.route('/disks/choose_disk_erase_chosen/<disk>')
def disks_choose_disk_erase_confirm(disk):
"""
Disk chosen, show before and after of disk configuration.
"""
partitions = current_app.config['CONFIG']['recipe']['create_partitions']
menu = current_app.config['CONFIG']['settings']['menu_order'].split(" ")
next_step_url = menu[menu.index("disks")+1]
if menu[menu.index("disks")] == 1:
previous_step_url = False
else:
previous_step_url = menu[menu.index("disks")-1]
blockdevs = lsblk.list_block_devices()
return render_template('disks_erase_confirmed.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, blockdevs=blockdevs,
diskname=disk, partitions=partitions
)
@bp.route('/disks/advanced')
def disks():
"""
Disks screen for the webui.
"""
blockdevs = lsblk.list_block_devices()
print(lsblk.list_block_devices())
menu = current_app.config['CONFIG']['settings']['menu_order'].split(" ")
next_step_url = menu[menu.index("disks")+1]
if menu[menu.index("disks")] == 1:
previous_step_url = False
else:
previous_step_url = menu[menu.index("disks")-1]
add_disks_button = '&nbsp; <button class="button iis-info"> <i class="fa fa-hdd-o" aria-hidden="true"></i> &nbsp; Add Disk or Filesystem </button>'
add_swap_button = '&nbsp; <button class="button iis-info"> <i class="fa fa-object-group" aria-hidden="true"></i> &nbsp; Swap Configuration </button>'
bottom_menu = add_disks_button + add_swap_button
# no bottom menu for this release
bottom_menu = ""
build_summary()
return render_template('disks_advanced.html', blockdevs=blockdevs,
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,
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>')
def disks_partition(part):
"""
Partition modal for the webui partition screen.
"""
print("Partition is: " + part)
partition = part
return render_template('disks_partition.html',
menu=current_app.config['CONFIG']['settings']['menu'],
partition=partition)
@bp.route('/disks/details/<disk>')
def disks_details(disk):
"""
Show some details about a disk.
"""
blockdevs = lsblk.list_block_devices()
return render_template('disks_details.html', disk=disk, blockdevs=blockdevs)
@bp.route('/disks/wipe_table/<disk>')
def disks_wipe_table(disk):
"""
Create a new partition table
"""
return render_template('disks_wipe_partition.html', disk=disk)
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']['disks'] = ("Disks", "/disks", 30)
def build_summary():
"""
Write up a summary of what this module will do.
"""
current_app.config['CONFIG']['Summary']['disks'] = {}
current_app.config['CONFIG']['Summary']['disks']['heading'] = "Disks and Partitions"
current_app.config['CONFIG']['Summary']['disks']['bleh'] = current_app.config['CONFIG']['recipe']['popcon']['enable_popcon']
current_app.config['CONFIG']['Summary']['disks']['text'] = "Pre-configured disk layout."
return("ok?")
build_menu()

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

View File

@@ -0,0 +1,7 @@
from flask import Blueprint
bp = Blueprint('hardware', __name__,
template_folder='')
from yasi_applets.hardware import routes

View 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 %}

View 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 = '&nbsp; <button class="button iis-info"> <i class="fa fa-cloud-download" aria-hidden="true"></i> &nbsp; Configure Network </button>'
blends_button = '&nbsp; <button class="button iis-info"> <i class="fa fa-download" aria-hidden="true"></i> &nbsp; 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()

View File

@@ -0,0 +1,9 @@
from flask import Blueprint
bp = Blueprint('install', __name__,
template_folder='',
static_folder='static',
static_url_path='/install/static')
from yasi_applets.install import routes

View File

@@ -10,7 +10,7 @@
<br />
<img style="width: 400px; padding: 20px;" src="/static/slide1.png" /> <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>

View File

@@ -1,4 +1,4 @@
from applets.install import bp
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
@@ -43,7 +43,7 @@ def run_script():
status["status"] = "running"
process = subprocess.Popen(
["bash", "/data/jonathan/devel/highvoltage/system-installer/daemon/src/fake-install-shell.sh"],
["bash", "/home/jonathan/devel/highvoltage/yasi/yasi-daemon/src/fake-install-shell.sh"],
stdout = subprocess.PIPE,
stderr = subprocess.STDOUT,
text = True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View 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

View 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 -->

View 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-trigger="click, keydown[altKey&&code=='F4'] from:body" hx-get="/main/quit" hx-swap="outerHTML"/><button class="button is-danger" > 🗙 </button></a>
</div>
</div> <!-- end pywebview-drag-region -->
<!-- End Header -->

View File

@@ -4,16 +4,19 @@
<div style="background-color: #424242; padding: 15px; border-radius: 15px; boders: none; color: white;">
<h1 class="is-size-4"> Help </h1>
<p class="title is-6"><span class="tag is-black">The help system is not yet implemented.</span>
<br>
<p>The help system is not yet implemented.</p>
<br>
<p>Some keyboard tips:<p>
<br>
<ul>
<li><button>ALT</button> + <button>n</button> or <button>CTRL</button>+<button>PGDn</button> moves to the next page.</li>
<li><button>ALT</button> + <button>p</button> or <button>CTRL</button>+<button>PGUp</button> moves to the previous page.</li>
</ul>
<br>
<div class="columns">
<a href="/welcome">
<div class="column"><button class="button is-light">Cancel</button></div>
</a>
<a href="/welcome"><div class="column"><button class="button is-link">Continue</button></div></a>
</div>
</div>

View 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>

View File

@@ -2,7 +2,8 @@
<div class="modal-background"></div>
<div class="modal-content">
<div style="background-color: #424242; padding: 15px; border-radius: 15px; borders: none; color: white;">
<div style="background-color: #424242; height: 180px; padding: 15px; border-radius: 15px; borders: none; color: white; position: fixed; left: 15px; top: 15px; bottom: 15px;">
<h1 class="is-size-4"> Main menu </h1>
<br />

View File

@@ -4,14 +4,14 @@
<div style="background-color: #424242; padding: 15px; border-radius: 15px; boders: none; color: white;">
<h1 class="is-size-4"> Exit system installer </h1>
<p class="title is-6"><span class="tag is-black">Quitting is not yet implemented.</span>
<br>
<p> Are you sure you want to quit? </p>
<br>
<div class="columns">
<a href="/welcome">
<div class="column"><button class="button is-light">Cancel</button></div>
</a>
<a href="/welcome"><div class="column"><button class="button is-link">Continue</button></div></a>
<a href="/welcome"><div class="column"><button class="button is-link">Back</button></div></a>
<a href=""><div class="column"><button onclick='pywebview.api.close()' class="button is-danger">Quit</button></div></a>
</div>
</div>
</div>

View File

@@ -1,10 +1,21 @@
from applets.welcome import bp
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
import dmm.lsblk as lsblk
# 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():
@@ -16,16 +27,7 @@ def index():
"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")
@bp.route('/main/help',methods=['GET', 'POST', 'PUT'])
@bp.route('/main/help',methods=['GET'])
def main_welcome():
"""
Manages the main help system.
@@ -33,7 +35,7 @@ def main_welcome():
return render_template('help.html')
@bp.route('/main/quit',methods=['GET', 'POST', 'PUT'])
@bp.route('/main/quit',methods=['GET'])
def main_quit():
"""
Manages the quit dialog.
@@ -41,9 +43,20 @@ def main_quit():
return render_template('quit.html')
@bp.route('/main/menu',methods=['GET', 'POST', 'PUT'])
@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

View File

@@ -0,0 +1 @@
/usr/share/fonts-fork-awesome/css/fork-awesome.css

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -10,6 +10,7 @@ body {
overflow: hidden;
min-width: 1050px;
min-height: 600px;
user-select: none;
}
html, body {margin: 0; height: 100%; overflow: hidden;}
@@ -23,19 +24,31 @@ html, body {margin: 0; height: 100%; overflow: hidden;}
position: absolute;
top: 0px;
bottom: 0px;
user-select: none;
}
.applet a:link a:hover a:active {
color: yellow;
}
.applet::-webkit-scrollbar {
display: none;
}
.applet {
width: 100%;
height: 442px;
height: 512px;
overflow-y: scroll;
overflow-x: hidden;
overflow: -moz-scrollbars-none;
}
.radio:hover {
color: #f1f1f1;
}
.pywebview-drag-region {
width: 100%;
height: 85px;
}

View 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

View File

@@ -1,4 +1,4 @@
from applets.software import bp
from yasi_applets.software import bp
from flask import Flask, request, session, redirect, \
url_for, render_template, flash, Blueprint
from flask import current_app
@@ -18,6 +18,8 @@ def webui_software():
sources_button = '&nbsp; <button class="button iis-info"> <i class="fa fa-cloud-download" aria-hidden="true"></i> &nbsp; Edit Sources </button>'
blends_button = '&nbsp; <button class="button iis-info"> <i class="fa fa-download" aria-hidden="true"></i> &nbsp; Install a Blend </button>'
bottom_menu = sources_button + blends_button
# Leave out useless buttons until they do more
bottom_menu = ''
build_summary()
return render_template('software.html',
@@ -26,7 +28,8 @@ def webui_software():
previous_step = previous_step_url,
next_step = next_step_url,
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'])
@@ -42,6 +45,19 @@ def software_settings():
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():
"""
Define menu items and paths.
@@ -58,7 +74,7 @@ def build_summary():
current_app.config['CONFIG']['Summary']['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']['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?")

View File

@@ -4,26 +4,45 @@
<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">
Popularity Contest
</span>
<div style="padding-left: 15px; padding-right: 15px; background-color: #fff;
color: #000;">
<big> Popularity Contest </big>
<br><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"
name="popcon" hx-post="/software/settings" hx-trigger="change"
{% if popcon %} checked {% endif %}>
<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>
</form>
<!--
<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">
@@ -56,5 +75,6 @@ Select software from Debian archives</span>
</div>
</div>
</div>
-->
{% endblock %}

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -3,5 +3,5 @@ from flask import Blueprint
bp = Blueprint('summary', __name__,
template_folder='')
from applets.summary import routes
from yasi_applets.summary import routes

View File

@@ -1,4 +1,4 @@
from applets.summary import bp
from yasi_applets.summary import bp
from flask import Flask, request, session, redirect, \
url_for, render_template, flash, Blueprint
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']))
summary = config['Summary']
print("Config is: ")
print(config)
return render_template('summary.html',
menu=current_app.config['CONFIG']['settings']['menu'],
menu_order=current_app.config['CONFIG']['settings']['menu_order'].split(),

Some files were not shown because too many files have changed in this diff Show More