Working on undo redo capabilities
This commit is contained in:
@@ -11,6 +11,7 @@ from components.drawerlayout.assets.icons import icon_panel_contract_regular, ic
|
||||
from components.drawerlayout.constants import DRAWER_LAYOUT_INSTANCE_ID
|
||||
from components.repositories.components.Repositories import Repositories
|
||||
from components.tabs.components.MyTabs import MyTabs
|
||||
from components.undo_redo.components.UndoRedo import UndoRedo
|
||||
from components.workflows.components.Workflows import Workflows
|
||||
from core.instance_manager import InstanceManager
|
||||
from core.settings_management import SettingsManager
|
||||
@@ -31,6 +32,7 @@ class DrawerLayout(BaseComponent):
|
||||
self._ai_buddy = self._create_component(AIBuddy)
|
||||
self._admin = self._create_component(Admin)
|
||||
self._applications = self._create_component(Applications)
|
||||
self._undo_redo = self._create_component(UndoRedo)
|
||||
|
||||
self.top_components = self._get_sub_components("TOP", [self._ai_buddy])
|
||||
self.bottom_components = self._get_sub_components("BOTTOM", [self._ai_buddy])
|
||||
@@ -53,12 +55,16 @@ class DrawerLayout(BaseComponent):
|
||||
name="sidebar"
|
||||
),
|
||||
Div(
|
||||
Label(
|
||||
Input(type="checkbox",
|
||||
onclick=f"document.getElementById('sidebar_{self._id}').classList.toggle('collapsed');"),
|
||||
icon_panel_contract_regular,
|
||||
icon_panel_expand_regular,
|
||||
cls="swap",
|
||||
Div(
|
||||
Label(
|
||||
Input(type="checkbox",
|
||||
onclick=f"document.getElementById('sidebar_{self._id}').classList.toggle('collapsed');"),
|
||||
icon_panel_contract_regular,
|
||||
icon_panel_expand_regular,
|
||||
cls="swap mr-4",
|
||||
),
|
||||
self._undo_redo,
|
||||
cls="flex"
|
||||
),
|
||||
Div(*[component for component in self.top_components], name="top", cls='dl-top'),
|
||||
Div(self._tabs, id=f"page_{self._id}", name="page", cls='dl-page'),
|
||||
|
||||
23
src/components/undo_redo/UndoRedoApp.py
Normal file
23
src/components/undo_redo/UndoRedoApp.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import logging
|
||||
|
||||
from fasthtml.fastapp import fast_app
|
||||
|
||||
from components.undo_redo.constants import Routes
|
||||
from core.instance_manager import debug_session, InstanceManager
|
||||
|
||||
logger = logging.getLogger("UndoRedoApp")
|
||||
|
||||
undo_redo_app, rt = fast_app()
|
||||
|
||||
|
||||
@rt(Routes.Undo)
|
||||
def post(session, _id: str):
|
||||
logger.debug(f"Entering {Routes.Undo} with args {debug_session(session)}, {_id=}")
|
||||
instance = InstanceManager.get(session, _id)
|
||||
return instance.undo()
|
||||
|
||||
@rt(Routes.Redo)
|
||||
def post(session, _id: str):
|
||||
logger.debug(f"Entering {Routes.Redo} with args {debug_session(session)}, {_id=}")
|
||||
instance = InstanceManager.get(session, _id)
|
||||
return instance.redo()
|
||||
0
src/components/undo_redo/__init__.py
Normal file
0
src/components/undo_redo/__init__.py
Normal file
0
src/components/undo_redo/assets/__init__.py
Normal file
0
src/components/undo_redo/assets/__init__.py
Normal file
7
src/components/undo_redo/assets/icons.py
Normal file
7
src/components/undo_redo/assets/icons.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from fastcore.basics import NotStr
|
||||
|
||||
# carbon Undo
|
||||
icon_undo = NotStr("""<svg name="undo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32"><path d="M20 10H7.815l3.587-3.586L10 5l-6 6l6 6l1.402-1.415L7.818 12H20a6 6 0 0 1 0 12h-8v2h8a8 8 0 0 0 0-16z" fill="currentColor"></path></svg>""")
|
||||
|
||||
# carbon Redo
|
||||
icon_redo = NotStr("""<svg name="redo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32"><path d="M12 10h12.185l-3.587-3.586L22 5l6 6l-6 6l-1.402-1.415L24.182 12H12a6 6 0 0 0 0 12h8v2h-8a8 8 0 0 1 0-16z" fill="currentColor"></path></svg>""")
|
||||
25
src/components/undo_redo/commands.py
Normal file
25
src/components/undo_redo/commands.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from components.BaseCommandManager import BaseCommandManager
|
||||
from components.undo_redo.constants import ROUTE_ROOT, Routes
|
||||
|
||||
|
||||
class UndoRedoCommandManager(BaseCommandManager):
|
||||
def __init__(self, owner):
|
||||
super().__init__(owner)
|
||||
|
||||
def undo(self):
|
||||
return {
|
||||
"hx-post": f"{ROUTE_ROOT}{Routes.Undo}",
|
||||
"hx-trigger": "click, keyup[ctrlKey&&key=='z'] from:body",
|
||||
"hx-target": f"#{self._id}",
|
||||
"hx-swap": "innerHTML",
|
||||
"hx-vals": f'{{"_id": "{self._id}"}}',
|
||||
}
|
||||
|
||||
def redo(self):
|
||||
return {
|
||||
"hx-post": f"{ROUTE_ROOT}{Routes.Redo}",
|
||||
"hx_trigger": "click, keyup[ctrlKey&&key=='y'] from:body",
|
||||
"hx-target": f"#{self._id}",
|
||||
"hx-swap": "innerHTML",
|
||||
"hx-vals": f'{{"_id": "{self._id}"}}',
|
||||
}
|
||||
89
src/components/undo_redo/components/UndoRedo.py
Normal file
89
src/components/undo_redo/components/UndoRedo.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from fasthtml.components import *
|
||||
|
||||
from components.BaseComponent import BaseComponentSingleton
|
||||
from components.undo_redo.assets.icons import icon_redo, icon_undo
|
||||
from components.undo_redo.commands import UndoRedoCommandManager
|
||||
from components.undo_redo.constants import UNDO_REDO_INSTANCE_ID
|
||||
from components_helpers import mk_icon
|
||||
|
||||
logger = logging.getLogger("UndoRedoApp")
|
||||
|
||||
|
||||
class CommandHistory(ABC):
|
||||
def __init__(self, name, desc):
|
||||
self.name = name
|
||||
self.desc = desc
|
||||
|
||||
@abstractmethod
|
||||
def undo(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def redo(self):
|
||||
pass
|
||||
|
||||
|
||||
class UndoRedo(BaseComponentSingleton):
|
||||
COMPONENT_INSTANCE_ID = UNDO_REDO_INSTANCE_ID
|
||||
|
||||
def __init__(self, session, _id, settings_manager=None, tabs_manager=None):
|
||||
super().__init__(session, _id, settings_manager, tabs_manager)
|
||||
self.index = 0
|
||||
self.history = []
|
||||
self._commands = UndoRedoCommandManager(self)
|
||||
|
||||
def push(self, command: CommandHistory):
|
||||
self.history.append(command)
|
||||
self.index += 1
|
||||
|
||||
def undo(self):
|
||||
logger.info(f"Undo command")
|
||||
return self
|
||||
|
||||
def redo(self):
|
||||
logger.info("Redo command")
|
||||
if self.index > 0:
|
||||
self.history.clear()
|
||||
self.index = 0
|
||||
else:
|
||||
self.push("something")
|
||||
return self
|
||||
|
||||
def __ft__(self):
|
||||
return Div(
|
||||
self._mk_undo(),
|
||||
self._mk_redo(),
|
||||
id=self._id,
|
||||
cls="flex"
|
||||
)
|
||||
|
||||
def _mk_undo(self):
|
||||
if self._can_undo():
|
||||
return mk_icon(icon_undo,
|
||||
size=24,
|
||||
**self._commands.undo())
|
||||
else:
|
||||
return mk_icon(icon_undo,
|
||||
size=24,
|
||||
can_select=False,
|
||||
cls="mmt-btn-disabled")
|
||||
|
||||
def _mk_redo(self):
|
||||
if self._can_redo():
|
||||
return mk_icon(icon_redo,
|
||||
size=24,
|
||||
**self._commands.redo())
|
||||
else:
|
||||
return mk_icon(icon_redo,
|
||||
size=24,
|
||||
can_select=False,
|
||||
cls="mmt-btn-disabled")
|
||||
|
||||
def _can_undo(self):
|
||||
return self.index > 0
|
||||
|
||||
def _can_redo(self):
|
||||
return self.index < len(self.history) - 1
|
||||
0
src/components/undo_redo/components/__init__.py
Normal file
0
src/components/undo_redo/components/__init__.py
Normal file
8
src/components/undo_redo/constants.py
Normal file
8
src/components/undo_redo/constants.py
Normal file
@@ -0,0 +1,8 @@
|
||||
UNDO_REDO_INSTANCE_ID = "__UndoRedo__"
|
||||
|
||||
ROUTE_ROOT = "/undo"
|
||||
|
||||
|
||||
class Routes:
|
||||
Undo = "/undo"
|
||||
Redo = "/redo"
|
||||
Reference in New Issue
Block a user