Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b412140d4 | |||
| 61157457b8 | |||
| 46cae312c8 | |||
| aa04718374 | |||
| 4c6495c4ee | |||
| 8f00ab9570 | |||
| 32dec36cd7 | |||
| f9b5c0d153 | |||
| b3dc60d950 | |||
| f8e93cedf2 | |||
| 074975650f | |||
| 7f654071d0 | |||
| 0711b55ad8 | |||
| 779d25def5 | |||
| bba6410bbd | |||
| edc5987293 | |||
| 2b6f0e41e6 | |||
| 444c2d3182 | |||
| a069cfe410 |
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
[autopve_demo.webm](https://github.com/natankeddem/autopve/assets/44515217/827bdd22-5311-43c1-9452-a56fa11998aa)
|
https://github.com/natankeddem/autopve/assets/44515217/9439e2e2-a7bf-4677-aea8-0684318bea6c
|
||||||
|
|
||||||
## Information
|
## Information
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,7 @@ class Drawer(object):
|
|||||||
el.IButton(icon="add", on_click=self._display_answer_dialog)
|
el.IButton(icon="add", on_click=self._display_answer_dialog)
|
||||||
self._buttons["remove"] = el.IButton(icon="remove", on_click=lambda: self._modify_answer("remove"))
|
self._buttons["remove"] = el.IButton(icon="remove", on_click=lambda: self._modify_answer("remove"))
|
||||||
self._buttons["edit"] = el.IButton(icon="edit", on_click=lambda: self._modify_answer("edit"))
|
self._buttons["edit"] = el.IButton(icon="edit", on_click=lambda: self._modify_answer("edit"))
|
||||||
|
self._buttons["content_copy"] = el.IButton(icon="content_copy", on_click=lambda: self._modify_answer("content_copy"))
|
||||||
ui.label(text="ANSWERS").classes("text-secondary")
|
ui.label(text="ANSWERS").classes("text-secondary")
|
||||||
self._table = (
|
self._table = (
|
||||||
ui.table(
|
ui.table(
|
||||||
@ -83,7 +84,7 @@ class Drawer(object):
|
|||||||
self._table.add_rows({"name": name})
|
self._table.add_rows({"name": name})
|
||||||
self._table.visible = True
|
self._table.visible = True
|
||||||
|
|
||||||
async def _display_answer_dialog(self, name=""):
|
async def _display_answer_dialog(self, name="", copy=False):
|
||||||
save = None
|
save = None
|
||||||
|
|
||||||
with ui.dialog() as answer_dialog, el.Card():
|
with ui.dialog() as answer_dialog, el.Card():
|
||||||
@ -100,6 +101,8 @@ class Drawer(object):
|
|||||||
|
|
||||||
def answer_check(value: str) -> Optional[bool]:
|
def answer_check(value: str) -> Optional[bool]:
|
||||||
spaceless = value.replace(" ", "")
|
spaceless = value.replace(" ", "")
|
||||||
|
if len(spaceless) == 0:
|
||||||
|
return False
|
||||||
for invalid_value in all_answers:
|
for invalid_value in all_answers:
|
||||||
if invalid_value == spaceless:
|
if invalid_value == spaceless:
|
||||||
return False
|
return False
|
||||||
@ -108,25 +111,28 @@ class Drawer(object):
|
|||||||
def enter_submit(e: KeyEventArguments) -> None:
|
def enter_submit(e: KeyEventArguments) -> None:
|
||||||
if e.key == "Enter" and save_ea.no_errors is True:
|
if e.key == "Enter" and save_ea.no_errors is True:
|
||||||
answer_dialog.submit("save")
|
answer_dialog.submit("save")
|
||||||
|
elif e.key == "Escape":
|
||||||
|
answer_dialog.close()
|
||||||
|
|
||||||
answer_input = el.VInput(label="answer", value=" ", invalid_characters="""'`"$\\;&<>|(){}""", invalid_values=all_answers, check=answer_check, max_length=20)
|
answer_input = el.VInput(label="answer", value=" ", invalid_characters="""'`"$\\;&<>|(){}""", invalid_values=all_answers, check=answer_check, max_length=20)
|
||||||
save_ea = el.ErrorAggregator(answer_input)
|
save_ea = el.ErrorAggregator(answer_input)
|
||||||
el.DButton("SAVE", on_click=lambda: answer_dialog.submit("save")).bind_enabled_from(save_ea, "no_errors")
|
el.DButton("SAVE", on_click=lambda: answer_dialog.submit("save")).bind_enabled_from(save_ea, "no_errors")
|
||||||
ui.keyboard(on_key=enter_submit, ignore=[])
|
ui.keyboard(on_key=enter_submit, ignore=[])
|
||||||
answer_input.value = name
|
answer_input.value = name
|
||||||
|
|
||||||
result = await answer_dialog
|
result = await answer_dialog
|
||||||
if result == "save":
|
answer = answer_input.value.strip()
|
||||||
answer = answer_input.value.strip()
|
if result == "save" and name != answer:
|
||||||
if len(answer) > 0 and name != "Default":
|
if name in storage.answers:
|
||||||
storage.answer(answer)
|
storage.answers[answer] = storage.answer(name, copy=True)
|
||||||
if name in storage.answers:
|
if copy is False:
|
||||||
storage.answers[answer] = storage.answer(name, copy=True)
|
|
||||||
del storage.answers[name]
|
del storage.answers[name]
|
||||||
for row in self._table.rows:
|
for row in self._table.rows:
|
||||||
if name == row["name"]:
|
if name == row["name"]:
|
||||||
self._table.remove_rows(row)
|
self._table.remove_rows(row)
|
||||||
self._add_answer_to_table(answer)
|
else:
|
||||||
|
storage.answer(answer)
|
||||||
|
self._add_answer_to_table(answer)
|
||||||
|
|
||||||
def _modify_answer(self, mode):
|
def _modify_answer(self, mode):
|
||||||
self._hide_content()
|
self._hide_content()
|
||||||
@ -152,17 +158,20 @@ class Drawer(object):
|
|||||||
|
|
||||||
async def _selected(self, e):
|
async def _selected(self, e):
|
||||||
self._hide_content()
|
self._hide_content()
|
||||||
if self._selection_mode == "edit":
|
if len(e.selection) == 1:
|
||||||
if len(e.selection) > 0 and e.selection[0]["name"] != "Default":
|
answer = e.selection[0]["name"]
|
||||||
await self._display_answer_dialog(name=e.selection[0]["name"])
|
if self._selection_mode == "content_copy":
|
||||||
if self._selection_mode == "remove":
|
await self._display_answer_dialog(name=answer, copy=True)
|
||||||
if len(e.selection) > 0:
|
self._modify_answer(None)
|
||||||
for row in e.selection:
|
elif answer == "Default":
|
||||||
if row["name"] != "Default":
|
self._table._props["selected"] = []
|
||||||
if row["name"] in storage.answers:
|
elif self._selection_mode == "edit":
|
||||||
del storage.answers[row["name"]]
|
await self._display_answer_dialog(name=answer)
|
||||||
self._table.remove_rows(row)
|
self._modify_answer(None)
|
||||||
self._modify_answer(None)
|
elif self._selection_mode == "remove":
|
||||||
|
if answer in storage.answers:
|
||||||
|
del storage.answers[answer]
|
||||||
|
self._table.remove_rows(e.selection[0])
|
||||||
|
|
||||||
async def _clicked(self, e):
|
async def _clicked(self, e):
|
||||||
if "name" in e.args[1]:
|
if "name" in e.args[1]:
|
||||||
|
|||||||
@ -14,92 +14,97 @@ class Setting(Tab):
|
|||||||
super().__init__(answer, type=type)
|
super().__init__(answer, type=type)
|
||||||
|
|
||||||
def _build(self):
|
def _build(self):
|
||||||
self.key_picker()
|
self.keys_controls()
|
||||||
|
|
||||||
def key_picker(self):
|
def keys_controls(self):
|
||||||
def keys_controls():
|
with ui.column() as col:
|
||||||
with ui.column() as col:
|
col.tailwind.width("[560px]").align_items("center")
|
||||||
col.tailwind.width("[560px]").align_items("center")
|
with ui.card() as card:
|
||||||
with ui.card() as card:
|
card.tailwind.width("full")
|
||||||
card.tailwind.width("full")
|
key_select = ui.select(list(self.keys.keys()), label="key", new_value_mode="add", with_input=True)
|
||||||
key_select = ui.select(list(self.keys.keys()), label="key", new_value_mode="add", with_input=True)
|
key_select.tailwind.width("full")
|
||||||
key_select.tailwind.width("full")
|
with ui.row() as row:
|
||||||
|
row.tailwind.width("full").align_items("center").justify_content("between")
|
||||||
with ui.row() as row:
|
with ui.row() as row:
|
||||||
row.tailwind.width("full").align_items("center").justify_content("between")
|
row.tailwind.align_items("center")
|
||||||
with ui.row() as row:
|
self.help = None
|
||||||
row.tailwind.align_items("center")
|
key = el.FInput(label="key", on_change=lambda e: self.key_changed(e.value), read_only=True)
|
||||||
self.help = None
|
key.bind_value_from(key_select)
|
||||||
key = el.FInput(label="key", on_change=lambda e: key_changed(e), read_only=True)
|
with ui.button(icon="help"):
|
||||||
key.bind_value_from(key_select)
|
self.help = ui.tooltip("NA")
|
||||||
|
ui.button(icon="add", on_click=lambda key=key: self.add_key(key.value))
|
||||||
|
ui.separator()
|
||||||
|
self._scroll = ui.scroll_area()
|
||||||
|
self._scroll.tailwind.width("full").height("[480px]")
|
||||||
|
items = storage.answer(self.answer)
|
||||||
|
if self.type is not None and self.type in items:
|
||||||
|
for key, value in items[self.type].items():
|
||||||
|
if isinstance(value, list):
|
||||||
|
self.add_key(key, "[" + ",".join(str(v) for v in value) + "]")
|
||||||
|
else:
|
||||||
|
self.add_key(key, str(value))
|
||||||
|
|
||||||
|
def add_key(self, key: str, value: str = ""):
|
||||||
|
if self.key_valid(key) is True:
|
||||||
|
with self._scroll:
|
||||||
|
with ui.row() as key_row:
|
||||||
|
key_row.tailwind.width("full").align_items("center").justify_content("between")
|
||||||
|
with ui.row() as row:
|
||||||
|
row.tailwind.align_items("center")
|
||||||
|
self._elements[key] = {
|
||||||
|
"control": el.FInput(
|
||||||
|
key,
|
||||||
|
password=True if key == "root_password" else False,
|
||||||
|
password_toggle_button=True if key == "root_password" else False,
|
||||||
|
autocomplete=self.keys[key]["options"] if key in self.keys and "options" in self.keys[key] else None,
|
||||||
|
on_change=lambda e, key=key: self.set_key(key, e.value),
|
||||||
|
),
|
||||||
|
"row": key_row,
|
||||||
|
}
|
||||||
|
self._elements[key]["control"].value = value
|
||||||
|
if key in self.keys:
|
||||||
with ui.button(icon="help"):
|
with ui.button(icon="help"):
|
||||||
self.help = ui.tooltip("NA")
|
ui.tooltip(self.keys[key]["description"])
|
||||||
ui.button(icon="add", on_click=lambda key=key: add_key(key.value))
|
ui.button(icon="remove", on_click=lambda _, key=key: self.remove_key(key))
|
||||||
ui.separator()
|
|
||||||
self._scroll = ui.scroll_area()
|
|
||||||
self._scroll.tailwind.width("full").height("[480px]")
|
|
||||||
items = storage.answer(self.answer)
|
|
||||||
if self.type is not None and self.type in items:
|
|
||||||
for key, value in items[self.type].items():
|
|
||||||
if isinstance(value, list):
|
|
||||||
add_key(key, "[" + ",".join(str(v) for v in value) + "]")
|
|
||||||
else:
|
|
||||||
add_key(key, str(value))
|
|
||||||
|
|
||||||
def add_key(key: str, value: str = ""):
|
def key_valid(self, key: str) -> bool:
|
||||||
if key is not None and key != "" and key not in self._elements.keys():
|
if key is not None and key != "" and key not in self._elements.keys():
|
||||||
with self._scroll:
|
return True
|
||||||
with ui.row() as key_row:
|
return False
|
||||||
key_row.tailwind.width("full").align_items("center").justify_content("between")
|
|
||||||
with ui.row() as row:
|
|
||||||
row.tailwind.align_items("center")
|
|
||||||
self._elements[key] = {
|
|
||||||
"control": el.FInput(
|
|
||||||
key,
|
|
||||||
password=True if key == "root_password" else False,
|
|
||||||
autocomplete=self.keys[key]["options"] if key in self.keys and "options" in self.keys[key] else None,
|
|
||||||
on_change=lambda e, key=key: set_key(key, e.value),
|
|
||||||
),
|
|
||||||
"row": key_row,
|
|
||||||
}
|
|
||||||
self._elements[key]["control"].value = value
|
|
||||||
if key in self.keys:
|
|
||||||
with ui.button(icon="help"):
|
|
||||||
ui.tooltip(self.keys[key]["description"])
|
|
||||||
ui.button(icon="remove", on_click=lambda _, key=key: remove_key(key))
|
|
||||||
|
|
||||||
def remove_key(key):
|
def remove_key(self, key: str):
|
||||||
self._scroll.remove(self._elements[key]["row"])
|
self._scroll.remove(self._elements[key]["row"])
|
||||||
del self._elements[key]
|
del self._elements[key]
|
||||||
|
if key in storage.answer(self.answer)[self.type]:
|
||||||
|
del storage.answer(self.answer)[self.type][key]
|
||||||
|
|
||||||
def set_key(key, value: str):
|
def set_key(self, key: str, value: str):
|
||||||
v: Any = None
|
v: Any = ""
|
||||||
if len(value) > 0:
|
if len(value) > 0:
|
||||||
if key in self.keys and "type" in self.keys[key]:
|
if key in self.keys and "type" in self.keys[key]:
|
||||||
if self.keys[key]["type"] == "list":
|
if self.keys[key]["type"] == "list":
|
||||||
v = value[1:-1].split(",")
|
v = value[1:-1].split(",")
|
||||||
elif self.keys[key]["type"] == "int":
|
elif self.keys[key]["type"] == "int":
|
||||||
v = int(value)
|
v = int(value)
|
||||||
else:
|
|
||||||
v = value
|
|
||||||
else:
|
else:
|
||||||
if len(value) > 2 and value.strip()[0] == "[" and value.strip()[-1] == "]":
|
v = value
|
||||||
v = value[1:-1].split(",")
|
else:
|
||||||
elif value.isnumeric():
|
if len(value) > 2 and value.strip()[0] == "[" and value.strip()[-1] == "]":
|
||||||
v = int(value)
|
v = value[1:-1].split(",")
|
||||||
else:
|
elif value.isnumeric():
|
||||||
v = value
|
v = int(value)
|
||||||
if self.type not in storage.answer(self.answer):
|
|
||||||
storage.answer(self.answer)[self.type] = {}
|
|
||||||
storage.answer(self.answer)[self.type][key] = v
|
|
||||||
|
|
||||||
def key_changed(e):
|
|
||||||
if self.help is not None:
|
|
||||||
if e.value in self.keys:
|
|
||||||
self.help.text = self.keys[e.value]["description"]
|
|
||||||
else:
|
else:
|
||||||
self.help.text = "NA"
|
v = value
|
||||||
|
if self.type not in storage.answer(self.answer):
|
||||||
|
storage.answer(self.answer)[self.type] = {}
|
||||||
|
storage.answer(self.answer)[self.type][key] = v
|
||||||
|
|
||||||
keys_controls()
|
def key_changed(self, value: str):
|
||||||
|
if self.help is not None:
|
||||||
|
if value in self.keys:
|
||||||
|
self.help.text = self.keys[value]["description"]
|
||||||
|
else:
|
||||||
|
self.help.text = "NA"
|
||||||
|
|
||||||
|
|
||||||
class Global(Setting):
|
class Global(Setting):
|
||||||
@ -163,3 +168,14 @@ class Disk(Setting):
|
|||||||
"btrfs.hdsize": {"description": ""},
|
"btrfs.hdsize": {"description": ""},
|
||||||
}
|
}
|
||||||
super().__init__(answer, type="disk-setup", keys=keys)
|
super().__init__(answer, type="disk-setup", keys=keys)
|
||||||
|
|
||||||
|
def key_valid(self, key: str) -> bool:
|
||||||
|
if super().key_valid(key) is True:
|
||||||
|
if "filter" in key and "disk_list" in self._elements.keys():
|
||||||
|
el.Notification(f"Can not add {key} when disk_list is utilized!", type="negative", timeout=5)
|
||||||
|
return False
|
||||||
|
elif key == "disk_list" and any("filter" in k for k in self._elements.keys()):
|
||||||
|
el.Notification("Can not add disk_list when a filter is utilized!", type="negative", timeout=5)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|||||||
@ -48,13 +48,11 @@ class System(Tab):
|
|||||||
with self.scroll:
|
with self.scroll:
|
||||||
with ui.row() as row:
|
with ui.row() as row:
|
||||||
row.tailwind.width("full").align_items("center").justify_content("between")
|
row.tailwind.width("full").align_items("center").justify_content("between")
|
||||||
with ui.row() as row:
|
self._elements[restriction] = {
|
||||||
row.tailwind.align_items("center")
|
"control": el.FInput(value=restriction, read_only=True),
|
||||||
self._elements[restriction] = {
|
"row": row,
|
||||||
"control": el.FInput(value=restriction, read_only=True),
|
}
|
||||||
"row": row,
|
self._elements[restriction]["control"].tailwind.width("[420px]")
|
||||||
}
|
|
||||||
self._elements[restriction]["control"].tailwind.width("[420px]")
|
|
||||||
ui.button(icon="remove", on_click=lambda _, r=restriction: remove_restriction(r))
|
ui.button(icon="remove", on_click=lambda _, r=restriction: remove_restriction(r))
|
||||||
if self.type not in storage.answer(self.answer):
|
if self.type not in storage.answer(self.answer):
|
||||||
storage.answer(self.answer)[self.type] = []
|
storage.answer(self.answer)[self.type] = []
|
||||||
|
|||||||
6
main.py
6
main.py
@ -102,6 +102,12 @@ async def post_answer(request: Request) -> PlainTextResponse:
|
|||||||
if "network" in default_data and "network" in answer_data:
|
if "network" in default_data and "network" in answer_data:
|
||||||
default_data["network"].update(answer_data["network"])
|
default_data["network"].update(answer_data["network"])
|
||||||
if "disk-setup" in default_data and "disk-setup" in answer_data:
|
if "disk-setup" in default_data and "disk-setup" in answer_data:
|
||||||
|
if any("filter" in k for k in answer_data["disk-setup"]):
|
||||||
|
del default_data["disk-setup"]["disk_list"]
|
||||||
|
if "disk_list" in answer_data["disk-setup"]:
|
||||||
|
for key in list(default_data["disk-setup"].keys()):
|
||||||
|
if "filter" in key:
|
||||||
|
del default_data["disk-setup"][key]
|
||||||
default_data["disk-setup"].update(answer_data["disk-setup"])
|
default_data["disk-setup"].update(answer_data["disk-setup"])
|
||||||
return response(answer, system_info, default_data)
|
return response(answer, system_info, default_data)
|
||||||
return response("Default", system_info, default_data)
|
return response("Default", system_info, default_data)
|
||||||
|
|||||||
Reference in New Issue
Block a user