Open Messj1 opened 3 years ago
I created some examples an put them on gist: https://gist.github.com/Messj1/de7a069c2199851fe3711a3729d96271
Once downloaded you can put them in <project-folder>/storybook/stories/design/RightBar
@MattiasNilsson can you please check this out and give me our opinions?
@Messj1 It looks great! Go ahead with it, what is the next step you plan to do with this?
@MattiasNilsson Good question ... I think the goal should be to simplify the whole HTML handling in a structural way. => in general separate: Data, Logic, Control and Design
In fact i don't know what would be better, to have a listening or a callable system. Maybe both :zany_face:
Any comment is welcome!
There are generated HTML files from the server and some CSS which handle the look and feel.
So next step would be to declare the listening data flow respectively data exchange. For example:
simple state binding with local storage save and restore:
<input type="checkbox" data-gui-datatype="input" data-gui-persist="local" name="wizzard.plugins" />
simple class toggle:
<div data-gui-datatype="bind" data-gui-name="screenloading" data-gui-class="toogleClassname">
</div>
simple attribute (open, disabled, checked, selected) toggle:
<details data-gui-datatype="input" data-gui-attribute="open">
</details>
Or something more complex example with component involved
<!-- listening component state -->
<input type="checkbox" data-gui-datatype="bind" data-gui-component="D3IndentedTree" name="isSearchRunning" />
<!-- listening event and call component -->
<input type="text" data-gui-datatype="input" data-gui-component="D3IndentedTree" name="treeFilter" />
Maybe some structure like this
data-gui: {
//indicates an data exchange element
"datatype": {
"default": null
"value": ["bind", "input"]
},
//component which is used to call and fetch data
"component": {
"default": "GUI",
"value": ["GUI", "Editor", "D3IndentedTree"]
},
//Name of action, variable or persist key
"name": {
"default": element is input? input.name
"value": *
},
//saves the "return" value in the selected storage. if no return save the getter
"persist": {
"default": null
"value": ["local", "session", "server"]
},
//toggle the CSS class
"class": {
"default": null
"value": "*",
"condition": [
"return" value is boolean,
]
},
}
Afterward DataBinder
and DataHandler
s module is used to fetch the data:
initialize
fetch data
trigger data event
So maybe there is also an Factory involved to get the right DataHandler
according to data-gui-datatype
.
The binding could be done in 3 ways as followed:
initialized find and bind in GUI after DOM is ready
// @module Typo3/CMS/FrontendEditing/GUI
init: function() {
...
this.findAndBindData();
}
register it later somewhere - we don't care :wink:
// inline
GUI.appendData(dataHandler);
or like runtime just in time --> for datatype
input only.
<input onclick="GUI.handleData" />
At least there would be much less code in GUI. In my opinion it should only bootstraps the whole application.
@Messj1 Great idea, right now all is interconnected.
@MattiasNilsson Yes, that is the reason why it is currently not testable. It is also (k)im possible to extend. I made some overview what the new GUI architecture could look like. It is currently in draft:
Editor
which is not a component. It is to much core feature of a frontend editing application.
BTW: The Editor
should be placed in a Registry
or something like this.FrontendEditor
because it should contain the business logic. The how to build.I split into several categories to show how they should work independently:
F.*
currentlyHint: the DataHandler
get coupled with GUI
due the DataBinder
, so as they are truly independent! :muscle: :godmode:
What do we win with all this heavy load bootstrap: :eyes:
I see no problem to make this changes without breaking anything because we are able to implement 2 ComponentFactory
and 2 DataBinder
, one as legacy mode and one with the new data-*
approach.
By the way we should also replace the javascript GlobalEventHandler
(onclick, ...) with help of DataBinder
cause of CSP.
Maybe something like
<div data-gui-datatype="trigger" data-gui-component="CE" data-gui-name="dragAndDrop">
...
</div>
Any feedback is welcome :wink:
I have now extended the diagram with the missing modules to get a real overview of the complete idea.
the compatibility check (red dashed line) is only the consequence of the idea to create factories outside the loader in server generated code. Would also be possible to handle in loader.
As we can see, the main work part of GUI is handled in components (see relation count).
DataHandler
coupling with Component
is handled by GUI
controller.
HTML coupling with component is handled by DataHandler
.
The Component
to EditorRegistry
relation exists only for EditorComponent
.
Missing part: How does Component
get partials (related component like an editor toolbar)
Component
give GUI
a hint what other Component
it would like to meet :thinking:And yes, I know that the Business Layer and especially Data Layer part is not finished. But the Idea is to get rid of undocumented calls since this is planed highly extendable. So everything in Business Layer get started by Action
. Action
only! :exploding_head:
Updated on 2020-03-02: simplified flow; abstracted data access in business layer with Interpreter
@Messj1 The only thing I can add is awesome! Just go ahead with it :)
I finished the big picture as an communication and interface overview.
There are some open issues like versioning. Eg. It is possible that Executers
of different versions or implementation get used parallel if components uses different Action
(Interface) version.
Note: Engine is a extendable State Machine and Executer
package contains Interpreter
(API) and Action
(ActionData
Interface)
I also made a rough component overview.
More details make no sense without prototype.
@Messj1 This is just something I have had in my head before. So cool! Which tool are you using for this? Just curious :)
@MattiasNilsson Yeah, cause I used to base structure of already existing components. So names are already known. :wink:
The big change is the Engine
and Excecuter
part which will gone be the game changer.
BTW is every package planed to be replaceable. So everything can be connect as it prefer.
I use diagrams.net. Previously known as draw.io. You can find the latest version in my branch: https://github.com/Messj1/frontend_editing/tree/488-Decouple-design-from-controller/Documentation/Assets
I use only the simplest functions. There are plenty of nice functions like the native mermaid
support but this becomes handy in a later phase.
There is also a layering system and you are able to preview data online with a data link. For example with the layered LegacyDataBinder
This becomes the next steps to close this issue an start another one with goal to rewrite the monolithic system into a modular (extendable) one.
@Messj1 Thanks for all the nice work! 👍
@MattiasNilsson found some small time slice to implement a simple prototype. Can you please have a look on it?
There is following structure:
Parser
with the already parsed information.DataHandler
which is the owner of the HTML and the component. Acts as a MVVM like ViewModel. It configures the HTML and Components. It also Listens on both to do the handling. (Bidirectional)DataBinder
to connect Parser
and Handler
together and configure handlers.I also added xstate.fsm
as a nice Finit State Machine (FSM) :nerd_face:
As a test component i implemented ToggleState
and glued it in storybook with the DataBinderWrapper
.
The main idea (currently) is to have an FSM as frontend (GUI) models and a extendable FSM as business model.
Storybook Test I have adapted the following Story /story/design-bar-right--default
<input type="checkbox" id="t3-frontend-editing__right-bar--open" />
) as the state of the rightPanel changeI'm insecure what would be better:
DataHandler
. Then the DataHandler
would become a DataBroker
.
:arrow_right: some kind of extendable ViewModel
['panelOpen', 'fullscreen']
) has to get somewhere. I see following options:
disabled
and transition to it from state panelClosed
listening on fullscreen while panelOpen
is goin into state hidden
fullscreen
and add transition hideButton
to it from state panelClosed
listening on fullscreen while panelOpen
has transition hide
DataHandler
. Eg. AnimationDataHandler
.panelOpen.fullscreen{...} .panelOpen{...} .fullscreen{...}
I think solution 1. would lead to create a DataHandler for every Component. This gives us an extra portion flexibility but i guess this is mostly not needed.
Would love to hear from you.
edit on 2021-03-25: added a show case branch an made git pages of this issue
@Messj1 I think solution 1 is the best to go with. Then it feels more organised :)
Hi
As part of improve code quality #432 and to improve extend ability there should be more separation of design and frontend-editing functionality.
I see following wrong dependencies flow:
In my opinion we should not attache events on server generated templates. The frontend editing GUI appearance should be part of the design or else you can only change color :unamused:
So what should GUI be?
It is used as
So it has to contain only bootstrap code and base composition logic code
What should be part of design
Everything that is generated on the server. So if it has to communicate we have to use
id
attribute because it should be unique or else it is to unclear what to do in GUI.So as a good example lets have look at a simple slide and open problem.
checkbox hack
So we could use a good old classic hack to save and transfer the state (usable in GUI with
t3-frontend-editing__right-bar
as id)Also possible to use radio instead of checkbox to get an real accordion :wink:
details
andsummary
elementsGood old
details
elements have the advanced, that the have anopen
attribute which indicate open or close.separate javascript based widgets
There are plenty technologies for js based widgets. From Web Components to attached function calls. From scripts to suits.
Conclusion
GUI should have different strategies to fetch data from the attached bindings like:
checked
attributselected
attributdata
attributopen
attributAt least there should be the opportunity to write an own editor and use only the base logic from frontend editing to transfer and handle data. I would love to see an different frontend editing GUI implementation.
Any opinions?