First Working version. I can add table
This commit is contained in:
39
src/components/addstuff/AddStuffApp.py
Normal file
39
src/components/addstuff/AddStuffApp.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import logging
|
||||
|
||||
from fasthtml.fastapp import fast_app
|
||||
|
||||
from components.addstuff.components.Repositories import Repositories
|
||||
from components.addstuff.constants import Routes
|
||||
from core.instance_manager import InstanceManager, debug_session
|
||||
|
||||
logger = logging.getLogger("AddStuffApp")
|
||||
|
||||
add_stuff_app, rt = fast_app()
|
||||
|
||||
|
||||
@rt(Routes.AddRepository)
|
||||
def get(session):
|
||||
repositories_instance = InstanceManager.get(session, Repositories.create_component_id(session))
|
||||
return repositories_instance.request_new_repository()
|
||||
|
||||
|
||||
@rt(Routes.AddRepository)
|
||||
def post(session, _id: str, tab_id: str, form_id: str, repository: str, table: str):
|
||||
logger.debug(
|
||||
f"Entering {Routes.AddRepository} with args {debug_session(session)}, {_id=}, {tab_id=}, {form_id=}, {repository=}, {table=}")
|
||||
instance = InstanceManager.get(session, _id) # Repository
|
||||
return instance.add_new_repository(tab_id, form_id, repository, table)
|
||||
|
||||
|
||||
@rt(Routes.SelectRepository)
|
||||
def put(session, _id: str, repository: str):
|
||||
logger.debug(f"Entering {Routes.SelectRepository} with args {debug_session(session)}, {_id=}, {repository=}")
|
||||
instance = InstanceManager.get(session, _id)
|
||||
return instance.select_repository(repository)
|
||||
|
||||
|
||||
@rt(Routes.ShowTable)
|
||||
def get(session, _id: str, repository: str, table: str):
|
||||
logger.debug(f"Entering {Routes.ShowTable} with args {debug_session(session)}, {_id=}, {repository=}, {table=}")
|
||||
instance = InstanceManager.get(session, _id)
|
||||
return instance.show_table(repository, table)
|
||||
0
src/components/addstuff/__init__.py
Normal file
0
src/components/addstuff/__init__.py
Normal file
0
src/components/addstuff/assets/__init__.py
Normal file
0
src/components/addstuff/assets/__init__.py
Normal file
3
src/components/addstuff/assets/addstuff.js
Normal file
3
src/components/addstuff/assets/addstuff.js
Normal file
@@ -0,0 +1,3 @@
|
||||
function bindRepositories(repositoryId) {
|
||||
bindTooltipsWithDelegation(repositoryId)
|
||||
}
|
||||
21
src/components/addstuff/assets/icons.py
Normal file
21
src/components/addstuff/assets/icons.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from fastcore.basics import NotStr
|
||||
|
||||
# Fluent Database20Regular
|
||||
icon_database = NotStr("""
|
||||
<svg name="database" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20">
|
||||
<g fill="none">
|
||||
<path d="M4 5c0-1.007.875-1.755 1.904-2.223C6.978 2.289 8.427 2 10 2s3.022.289 4.096.777C15.125 3.245 16 3.993 16 5v10c0 1.007-.875 1.755-1.904 2.223C13.022 17.71 11.573 18 10 18s-3.022-.289-4.096-.777C4.875 16.755 4 16.007 4 15V5zm1 0c0 .374.356.875 1.318 1.313C7.234 6.729 8.536 7 10 7s2.766-.27 3.682-.687C14.644 5.875 15 5.373 15 5c0-.374-.356-.875-1.318-1.313C12.766 3.271 11.464 3 10 3s-2.766.27-3.682.687C5.356 4.125 5 4.627 5 5zm10 1.698a4.92 4.92 0 0 1-.904.525C13.022 7.711 11.573 8 10 8s-3.022-.289-4.096-.777A4.92 4.92 0 0 1 5 6.698V15c0 .374.356.875 1.318 1.313c.916.416 2.218.687 3.682.687s2.766-.27 3.682-.687C14.644 15.875 15 15.373 15 15V6.698z" fill="currentColor">
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
||||
""")
|
||||
|
||||
# Fluent Table20Regular
|
||||
icon_table = NotStr("""
|
||||
<svg name="table" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20">
|
||||
<g fill="none">
|
||||
<path d="M17 5.5A2.5 2.5 0 0 0 14.5 3h-9A2.5 2.5 0 0 0 3 5.5v9A2.5 2.5 0 0 0 5.5 17h9a2.5 2.5 0 0 0 2.5-2.5v-9zm-13 9V13h3v3H5.5l-.144-.007A1.5 1.5 0 0 1 4 14.5zm8-1.5v3H8v-3h4zm2.5 3H13v-3h3v1.5l-.007.145A1.5 1.5 0 0 1 14.5 16zM12 8v4H8V8h4zm1 0h3v4h-3V8zm-1-4v3H8V4h4zm1 0h1.5l.145.007A1.5 1.5 0 0 1 16 5.5V7h-3V4zM7 4v3H4V5.5l.007-.144A1.5 1.5 0 0 1 5.5 4H7zm0 4v4H4V8h3z" fill="currentColor">
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
||||
""")
|
||||
34
src/components/addstuff/components/AddStuffMenu.py
Normal file
34
src/components/addstuff/components/AddStuffMenu.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from fasthtml.components import *
|
||||
|
||||
from components.BaseComponent import BaseComponent
|
||||
from components.addstuff.constants import ADD_STUFF_INSTANCE_ID, ROUTE_ROOT, Routes
|
||||
from components.addstuff.settings import AddStuffSettingsManager
|
||||
|
||||
|
||||
class AddStuffMenu(BaseComponent):
|
||||
def __init__(self, session: dict, _id: str, settings_manager=None, tabs_manager=None):
|
||||
super().__init__(session, _id)
|
||||
self.tabs_manager = tabs_manager # MyTabs component id
|
||||
self.mappings = {} # to keep track of when element is displayed on which tab
|
||||
self.settings = AddStuffSettingsManager(session, settings_manager)
|
||||
|
||||
def __ft__(self):
|
||||
return Div(
|
||||
Div("Add stuff...", tabindex="0"),
|
||||
Ul(
|
||||
Li(A("Add Database",
|
||||
hx_get=f"{ROUTE_ROOT}{Routes.AddRepository}",
|
||||
hx_target=f"#{self.tabs_manager.get_id()}",
|
||||
hx_swap="outerHTML",
|
||||
)),
|
||||
Li(A("Add Application")),
|
||||
tabindex="0",
|
||||
cls="menu menu-sm dropdown-content bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm"
|
||||
),
|
||||
|
||||
cls="dropdown dropdown-hover"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def create_component_id(session):
|
||||
return f"{ADD_STUFF_INSTANCE_ID}{session['user_id']}"
|
||||
156
src/components/addstuff/components/Repositories.py
Normal file
156
src/components/addstuff/components/Repositories.py
Normal file
@@ -0,0 +1,156 @@
|
||||
import logging
|
||||
|
||||
from fasthtml.components import *
|
||||
from fasthtml.xtend import Script
|
||||
|
||||
from components.BaseComponent import BaseComponent
|
||||
from components.addstuff.assets.icons import icon_database, icon_table
|
||||
from components.addstuff.constants import REPOSITORIES_INSTANCE_ID, ROUTE_ROOT, Routes
|
||||
from components.addstuff.settings import AddStuffSettingsManager, MyTable, Repository
|
||||
from components.datagrid_new.components.DataGrid import DataGrid
|
||||
from components.form.components.MyForm import MyForm, FormField
|
||||
from components_helpers import mk_icon, mk_ellipsis, mk_tooltip_container
|
||||
from core.instance_manager import InstanceManager
|
||||
|
||||
logger = logging.getLogger("Repositories")
|
||||
|
||||
|
||||
class Repositories(BaseComponent):
|
||||
def __init__(self, session: dict, _id: str, settings_manager=None, tabs_manager=None):
|
||||
super().__init__(session, _id)
|
||||
self._settings_manager = settings_manager
|
||||
self.repo_settings_manager = AddStuffSettingsManager(session, settings_manager)
|
||||
self.tabs_manager = tabs_manager
|
||||
self._contents = {} # ket tracks of already displayed contents
|
||||
|
||||
def request_new_repository(self):
|
||||
# request for a new tab_id
|
||||
new_tab_id = self.tabs_manager.request_new_tab_id()
|
||||
|
||||
# create a new form to ask for the details of the new database
|
||||
add_repository_form = self._mk_add_repository_form(new_tab_id)
|
||||
|
||||
# create and display the form in a new tab
|
||||
self.tabs_manager.add_tab("Add Database", add_repository_form, tab_id=new_tab_id)
|
||||
return self.tabs_manager
|
||||
|
||||
def add_new_repository(self, tab_id: str, form_id: str, repository_name: str, table_name: str):
|
||||
"""
|
||||
|
||||
:param tab_id: tab id where the table content will be displayed (and where the form was displayed)
|
||||
:param form_id: form used to give the repository name (to be used in case of error)
|
||||
:param repository_name: new repository name
|
||||
:param table_name: default table name
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
# Add the new repository and its default table to the list of repositories
|
||||
tables = [MyTable(table_name, {})] if table_name else []
|
||||
repository = self.repo_settings_manager.add_repository(repository_name, tables)
|
||||
|
||||
# update the tab content with table content
|
||||
key = (repository_name, table_name)
|
||||
self.tabs_manager.set_tab_content(tab_id,
|
||||
self._get_table_content(key),
|
||||
title=table_name,
|
||||
key=key,
|
||||
active=True)
|
||||
|
||||
return self._mk_repository(repository, True), self.tabs_manager.refresh()
|
||||
|
||||
except ValueError as ex:
|
||||
logger.debug(f" Repository '{repository_name}' already exists.")
|
||||
add_repository_form = InstanceManager.get(self._session, form_id)
|
||||
add_repository_form.set_error(ex)
|
||||
|
||||
return self.tabs_manager.refresh()
|
||||
|
||||
def select_repository(self, repository_name: str):
|
||||
self.repo_settings_manager.select_repository(repository_name)
|
||||
|
||||
def show_table(self, repository_name: str, table_name: str):
|
||||
key = (repository_name, table_name)
|
||||
self.tabs_manager.add_tab(table_name, self._get_table_content(key), key)
|
||||
return self.tabs_manager
|
||||
|
||||
def refresh(self):
|
||||
return self._mk_repositories(oob=True)
|
||||
|
||||
def __ft__(self):
|
||||
return Div(
|
||||
mk_tooltip_container(self._id),
|
||||
Div(cls="divider"),
|
||||
mk_ellipsis("Repositories", cls="text-sm font-medium mb-1"),
|
||||
self._mk_repositories(),
|
||||
Script(f"bindRepositories('{self._id}')")
|
||||
)
|
||||
|
||||
def _mk_repositories(self, oob=False):
|
||||
settings = self.repo_settings_manager.get_settings()
|
||||
return Div(
|
||||
*[self._mk_repository(repo, repo.name == settings.selected_repository_name)
|
||||
for repo in settings.repositories],
|
||||
|
||||
id=self._id,
|
||||
hx_swap_oob="true" if oob else None,
|
||||
)
|
||||
|
||||
def _mk_repository(self, repo: Repository, selected):
|
||||
return Div(
|
||||
Input(type="radio",
|
||||
name=f"repo-accordion-{self._id}",
|
||||
checked="checked" if selected else None,
|
||||
cls="p-0! min-h-0!",
|
||||
hx_put=f"{ROUTE_ROOT}{Routes.SelectRepository}",
|
||||
hx_vals=f'{{"_id": "{self._id}", "repository": "{repo.name}"}}',
|
||||
# hx_trigger="changed delay:500ms",
|
||||
),
|
||||
Div(
|
||||
mk_icon(icon_database, can_select=False), mk_ellipsis(repo.name),
|
||||
cls="collapse-title p-0 min-h-0 flex truncate",
|
||||
),
|
||||
Div(
|
||||
*[
|
||||
Div(mk_icon(icon_table, can_select=False), mk_ellipsis(table.name),
|
||||
name="repo-table",
|
||||
hx_get=f"{ROUTE_ROOT}{Routes.ShowTable}",
|
||||
hx_target=f"#{self.tabs_manager.get_id()}",
|
||||
hx_swap="outerHTML",
|
||||
hx_vals=f'{{"_id": "{self._id}", "repository": "{repo.name}", "table": "{table.name}"}}',
|
||||
cls="flex")
|
||||
for table in repo.tables
|
||||
],
|
||||
cls="collapse-content pr-0! truncate",
|
||||
),
|
||||
tabindex="0", cls="collapse mb-2")
|
||||
|
||||
def _mk_add_repository_form(self, tab_id: str):
|
||||
htmx_params = {
|
||||
"hx-post": f"{ROUTE_ROOT}{Routes.AddRepository}",
|
||||
"hx-target": f"#{self._id}",
|
||||
"hx-swap": "beforeend",
|
||||
}
|
||||
return InstanceManager.get(self._session, MyForm.create_component_id(self._session), MyForm,
|
||||
title="Add Repository",
|
||||
fields=[FormField("repository", 'Repository Name', 'input'),
|
||||
FormField("table", 'First Table Name', 'input')],
|
||||
htmx_params=htmx_params,
|
||||
extra_values={"_id": self._id, "tab_id": tab_id})
|
||||
|
||||
def _get_table_content(self, key):
|
||||
|
||||
if key in self._contents:
|
||||
return self._contents[key]
|
||||
|
||||
dg = InstanceManager.get(self._session,
|
||||
DataGrid.create_component_id(self._session),
|
||||
DataGrid,
|
||||
settings_manager=self._settings_manager,
|
||||
key=key)
|
||||
|
||||
self._contents[key] = dg
|
||||
return dg
|
||||
|
||||
@staticmethod
|
||||
def create_component_id(session):
|
||||
return f"{REPOSITORIES_INSTANCE_ID}{session['user_id']}"
|
||||
0
src/components/addstuff/components/__init__.py
Normal file
0
src/components/addstuff/components/__init__.py
Normal file
9
src/components/addstuff/constants.py
Normal file
9
src/components/addstuff/constants.py
Normal file
@@ -0,0 +1,9 @@
|
||||
ADD_STUFF_INSTANCE_ID = "__AddStuff__"
|
||||
ADD_DATABASE_INSTANCE_ID = "__AddDatabase__"
|
||||
REPOSITORIES_INSTANCE_ID = "__Repositories__"
|
||||
ROUTE_ROOT = "/add"
|
||||
|
||||
class Routes:
|
||||
AddRepository = "/add-repository"
|
||||
SelectRepository = "/select-repository"
|
||||
ShowTable = "/show-table"
|
||||
99
src/components/addstuff/settings.py
Normal file
99
src/components/addstuff/settings.py
Normal file
@@ -0,0 +1,99 @@
|
||||
import dataclasses
|
||||
import logging
|
||||
|
||||
from core.settings_management import SettingsManager
|
||||
from core.settings_objects import BaseSettingObj
|
||||
|
||||
ADD_STUFF_SETTINGS_ENTRY = "AddStuffSettings"
|
||||
|
||||
logger = logging.getLogger("AddStuffSettings")
|
||||
|
||||
@dataclasses.dataclass
|
||||
class MyTable:
|
||||
name: str
|
||||
settings: dict | None = None
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Repository:
|
||||
name: str
|
||||
tables: list[MyTable]
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class AddStuffSettings:
|
||||
repositories: list[Repository] = dataclasses.field(default_factory=list)
|
||||
selected_repository_name: str = None
|
||||
|
||||
|
||||
class AddStuffSettingsManager(BaseSettingObj):
|
||||
__ENTRY_NAME__ = ADD_STUFF_SETTINGS_ENTRY
|
||||
|
||||
def __init__(self, session: dict, settings_manager: SettingsManager):
|
||||
self.session = session
|
||||
self.settings_manager = settings_manager
|
||||
|
||||
def get_settings(self):
|
||||
return self.settings_manager.get(self.session, ADD_STUFF_SETTINGS_ENTRY, default=AddStuffSettings())
|
||||
|
||||
def add_repository(self, repository_name: str, tables: list[MyTable] = None):
|
||||
"""
|
||||
Adds a new repository to the list of repositories. The repository is identified
|
||||
by its name and can optionally include a list of associated tables.
|
||||
|
||||
:param repository_name: The name of the repository to be added.
|
||||
:param tables: A list of Table objects to be associated with the repository,
|
||||
defaulting to an empty list if not provided.
|
||||
:type tables: list[Table], optional
|
||||
:return: None
|
||||
"""
|
||||
|
||||
settings = self.get_settings()
|
||||
|
||||
if repository_name is None or repository_name == "":
|
||||
raise ValueError("Repository name cannot be empty.")
|
||||
|
||||
if repository_name in [repo.name for repo in settings.repositories]:
|
||||
raise ValueError(f"Repository '{repository_name}' already exists.")
|
||||
|
||||
existing_repositories = [r.name for r in settings.repositories]
|
||||
logger.info(f"Existing repositories:{existing_repositories}")
|
||||
|
||||
repository = Repository(repository_name, tables or [])
|
||||
settings.repositories.append(repository)
|
||||
self.settings_manager.put(self.session, ADD_STUFF_SETTINGS_ENTRY, settings)
|
||||
return repository
|
||||
|
||||
def add_table(self, repository_name: str, table_name: str, table_settings: dict):
|
||||
"""
|
||||
Adds a table to the specified repository
|
||||
|
||||
:param repository_name: The name of the target repository.
|
||||
:param table_name: The name of the table to add.
|
||||
:param table_settings: A dictionary containing the settings or configuration details
|
||||
of the table.
|
||||
:return: None
|
||||
"""
|
||||
settings = self.get_settings()
|
||||
|
||||
repository = next(filter(lambda r: r.name == repository_name, settings.repositories), None)
|
||||
if repository is None:
|
||||
raise ValueError(f"Repository '{repository_name}' does not exists.")
|
||||
|
||||
if table_name in (t.name for t in repository.tables):
|
||||
raise ValueError(f"Table '{table_name}' already exists.")
|
||||
|
||||
repository.tables.append(MyTable(table_name, table_settings))
|
||||
self.settings_manager.put(self.session, ADD_STUFF_SETTINGS_ENTRY, settings)
|
||||
|
||||
def select_repository(self, repository_name: str):
|
||||
"""
|
||||
Select and save the specified repository name in the current session's settings.
|
||||
|
||||
:param repository_name: The name of the repository to be selected and stored.
|
||||
:type repository_name: str
|
||||
:return: None
|
||||
"""
|
||||
settings = self.get_settings()
|
||||
settings.selected_repository_name = repository_name
|
||||
self.settings_manager.put(self.session, ADD_STUFF_SETTINGS_ENTRY, settings)
|
||||
Reference in New Issue
Block a user