Hi Gavin, Clearly, our POC json response for EditPerson is much more verbose :-)
Your example show us that it's possible to reduce number of level in hierarchy ;-) When I work on documentation/comment/javadoc JsonRenderer, I review what attribute is really use / usable and so I remove some. In one or two month, it will be better { "viewScreenName":"EditPerson", "viewEntities":{}, "viewScreen":[ { "name":"Form", "attributes":{ "viewSize":20, "formType":"single", "autocomplete":"", "containerStyle":"", "viewIndex":0, "focusFieldName":"salutation", "useRowSubmit":false, "entityName":"", "hasRequiredField":"Y", "linkUrl":"/partymgrfjs/control/updatePerson", "name":"EditPerson", "containerId":"EditPerson", "viewSizeField":"viewSize_0", "viewIndexField":"viewIndex_0", "targetWindow":""}}]} "children":[ { "name":"HiddenField", "attributes":{ "conditionGroup":"", "formName":"EditPerson", "name":"partyId", "id":"EditPerson_partyId", "event":"", "value":"sfa101" } }, { "name":"SingleWrapper", "attributes":{ "formName":"EditPerson", "style":"basic-table" } "children":[ { "name":"FieldRow", "attributes":{} "children":[ { "name":"FieldRowTitleCell", "attributes":{} }, { "name":"FieldRowWidgetCell", "attributes":{ "positionSpan":1, "style":"" } "children":[ { "name":"DisplayField", "attributes":{ "idName":"EditPerson_partyId", "alert":"true", "formName":"EditPerson", "name":"partyId", "description":"sfa101", "type":"text" } }] }] }, { "name":"FieldRow", "attributes":{} "children":[ { "name":"FieldRowTitleCell", "attributes":{} "children":[ { "name":"FieldTitle", "attributes":{ "fieldHelpText":"", "for":"EditPerson_partyId", "style":"", "id":"EditPerson_partyId", "title":"Party ID" } }] }, { "name":"FieldRowWidgetCell", "attributes":{ "positionSpan":1, "style":"" } "children":[ { "name":"TextField", "attributes":{ "textSize":40, "maxlength":60, "clientAutocomplete":"true", "required":{ "requiredField":"false", "requiredStyle":"" }, "ajaxEnabled":true, "delegatorName":"default", "readonly":false, "alert":"false", "formName":"EditPerson", "name":"salutation", "disabled":false, "id":"EditPerson_salutation", "value":"" } }] }] }, { "name":"FieldRow", "attributes":{} "children":[ { "name":"FieldRowTitleCell", "attributes":{} "children":[ { "name":"FieldTitle", "attributes":{ "fieldHelpText":"", "for":"EditPerson_firstName", "style":"", "id":"EditPerson_firstName", "title":"Party ID" } }] }, { "name":"FieldRowWidgetCell", "attributes":{ "positionSpan":1, "style":"" } "children":[ { "name":"TextField", "attributes":{ "textSize":40, "maxlength":60, "className:"required" "clientAutocomplete":"true", "required":{ "requiredField":"true", "requiredStyle":"" }, "ajaxEnabled":true, "delegatorName":"default", "readonly":false, "alert":"false", "formName":"EditPerson", "name":"firstName", "disabled":false, "id":"EditPerson_firstName", "value":"John" } }] }] }, { .... Le 20/12/2019 à 16:22, Gavin Mabie a écrit : > Thanks Olivier > > You said: When rendering, as JSON flow, for some "field", it's not easily > to say what is only data, what is user presentation data. > > Here's a JSON response for A EditPerson Form: > { > "target": "createClient", > "targetWindow": "", > "fields": [ > { > "title": "Role Type Id", > "name": "roleTypeId", > "event": "", > "id": "EditPerson_roleTypeId", > "value": "HOMEINIT_CLIENT", > "required": false, > "type": "hidden" > }, > { > "title": "First Name", > "name": "firstName", > "value": "", > "id": "EditPerson_firstName", > "required": true, > "type": "text" > }, > { > "title": "Last Name", > "name": "lastName", > "value": "", > "id": "EditPerson_lastName", > "required": true, > "type": "text" > }, > { > "title": "Gender", > "name": "gender", > "value": "", > "id": "EditPerson_gender", > "required": false, > "type": "dropdown", > "allOptionValues": [ > { > "key": "M", > "description": "Male" > }, > { > "key": "F", > "description": "Female" > } > ], > "textSize": 0 > }, > { > "title": "Birth Date", > "name": "birthDate", > "value": "", > "id": "EditPerson_birthDate", > "required": false, > "type": "datetime" > }, > { > "title": "Height", > "name": "height", > "value": "", > "id": "EditPerson_height", > "event": "", > "required": false, > "type": "text" > }, > { > "title": "Weight", > "name": "weight", > "value": "", > "id": "EditPerson_weight", > "event": "", > "required": false, > "type": "text" > }, > { > "title": "Marital Status", > "name": "maritalStatus", > "value": "", > "id": "EditPerson_maritalStatus", > "event": "", > "required": false, > "type": "dropdown", > "allOptionValues": [ > { > "key": "S", > "description": "Single" > }, > { > "key": "M", > "description": "Married" > }, > { > "key": "P", > "description": "Separated" > }, > { > "key": "D", > "description": "Divorced" > }, > { > "key": "W", > "description": "Widowed" > } > ], > "textSize": 0 > }, > { > "title": "RSA ID", > "name": "socialSecurityNumber", > "value": "", > "id": "EditPerson_socialSecurityNumber", > "required": false, > "type": "text" > }, > { > "title": "Passport Number", > "name": "passportNumber", > "value": "", > "id": "EditPerson_passportNumber", > "required": false, > "type": "text" > }, > { > "title": "Employment Status Enum Id", > "name": "employmentStatusEnumId", > "value": "", > "id": "EditPerson_employmentStatusEnumId", > "event": "", > "required": false, > "type": "dropdown", > "allOptionValues": [ > { > "key": "EMPS_FULLTIME", > "description": "Full-time Employed [FULLTIME]" > }, > { > "key": "EMPS_PARTTIME", > "description": "Part-time Employed [PARTTIME]" > }, > { > "key": "EMPS_SELF", > "description": "Self Employed [SELF]" > }, > { > "key": "EMPS_HOUSE", > "description": "House-Person [HOUSE]" > }, > { > "key": "EMPS_RETIRED", > "description": "Retired [RETIRED]" > }, > { > "key": "EMPS_STUDENT", > "description": "Student [STUDENT]" > }, > { > "key": "EMPS_UNEMP", > "description": "Unemployed [UNEMP]" > } > ], > "textSize": 0 > }, > { > "title": "Residence Status Enum Id", > "name": "residenceStatusEnumId", > "value": "", > "id": "EditPerson_residenceStatusEnumId", > "event": "", > "required": false, > "type": "dropdown", > "allOptionValues": [ > { > "key": "PRESS_OWN", > "description": "Own Home [OWN]" > }, > { > "key": "PRESS_PVT_TENANT", > "description": "Private Tenant [PVT_TENANT]" > }, > { > "key": "PRESS_PUB_TENANT", > "description": "Public Tenant [PUB_TENANT]" > }, > { > "key": "PRESS_PARENTS", > "description": "With Parents [PARENTS]" > } > ], > "textSize": 0 > }, > { > "title": "Status ID", > "name": "statusId", > "value": "", > "id": "EditPerson_statusId", > "required": false, > "type": "text" > }, > { > "title": "Save", > "name": "submitButton", > "value": "", > "id": "EditPerson_submitButton", > "event": "", > "required": false > }, > { > "title": " ", > "name": "cancelLink", > "value": "", > "id": "EditPerson_cancelLink", > "event": "", > "required": false > } > ] > } > > All the fields and their attributes generated by Ofbiz are included in the > JSON response. > > Good luck with you POC. > > Cheers > > Gavin > > > > On Fri, Dec 20, 2019 at 4:10 PM Olivier Heintz <holiv...@apache.org> wrote: > >> Hi Gavin, >> >> Separation completely GUI and application could be exploring, but I think >> it will be in a future step. >> >> Currently, one of step which can easily be done is having API for all >> services already used by the screen, (the future POST, PUT, PATCH and >> DELETE) >> be able to call them without a screen as return flow, return flow will be >> only success or error and messages associated >> Maybe a controller file could be dedicated by component with these URI. >> I supposed , you have done something similar for your Angular custom app, >> for the POC-VueJS it's needed. >> >> Separation completely GUI from application needed too, to be able to have >> GET to read data, to know which data to send in which context, and currently >> it's, most of time, executed/filtered by screen/forms. >> Realize a complete new set of API for GET using logic used by screen/form >> (security / display-entity, ...) will be a very large task and I think it >> will be better to work on using screen/form and having a correct rendering >> data on a intermediate step. >> Difficulties to have a correct data rendering is : >> When rendering, as JSON flow, for some "field", it's not easily to say >> what is only data, what is user presentation data. I will try to explain by >> some example : >> 1) field with hyperlink, >> * only data is clear it's description, but when it's a image the data is >> more the image logical name (edit / remove / deactivate ...) >> * hyperlink parameters : I think it's data but on the data sent is it >> sub-data of fieldName or data at the same level >> 2) field display, >> * red-when is it data ? >> * format, if it exist, data should be with format used or not >> 3) required attribute : is it data >> >> I think it is possible to decide for each what is the choice of the >> community but as a intermediate step send a little more data is a solution >> too ;-) >> >> In the POC-VueJs, we have decided to send screen/form tag and attributes, >> this gives the user/SPA-GUI-developer the choice >> >> Olivier >> >> PS: Many thanks for your questions / remarks, they helped me to see things >> more clearly, and to decide the points to continue to study or where to go >> for the next step. >> >> >> Le 17/12/2019 à 12:28, Gavin Mabie a écrit : >>> Hi Oliver >>> >>> I think separating the GUI completely from the application layer could be >>> an option worthy of exploring. That would mean api requests and with >>> standard responses in JSON or XML. What the end user does with the >>> response is entirely up to him/her. In this scenario the responses and >>> their shapes are highly structured leaving the chosen GUI framework up to >>> the user. Not easy as business/workflow processes would have to be >>> represented by well defined api endpoints. Although the current view >>> renderer accommodates abstraction for different view implementations it >>> only really result in HTML in the end. >>> >>> Your question: is it clever to have same functionality with the multiple >>> renderer? >>> My response: don't have a view renderer at all. >>> >>> What do you think? >>> >>> Gavin >>> >>> >>> On Tue, Dec 17, 2019 at 12:22 PM Olivier Heintz <holiv...@apache.org> >> wrote: >>> >>>> Hello Taher, >>>> >>>>> Do you want an SPA framework now or in the future, >>>> is a very important question but >>>> which road to use to go is important too. >>>> >>>> As with the current gui renderer architecture, it's possible to have >>>> multiple rendrer engine for the "same" screen/menu/form xml files, >>>> one question is : is it clever to have same functionality with the >>>> multiple renderer ? >>>> maybe the html should be oriented low-technology approach, and so no >>>> javascript or minimum (in futur) >>>> the SPA should oriented multi-device and "modern" approach >>>> >>>> In all case evolution can be step by step and having clear xml formal >>>> expression for user interaction is good. >>>> >>>> With POC-VueJs we wanted to answerd to the question : is it possible to >>>> have screen/menu/form xml files AND SPA renderer with all advantage of >> SPA. >>>> Currently, answer is clearly Yes. >>>> Our choices or codes are maybe not correct but it's not with a lot of >>>> workaround to be able to say it works. >>>> Some value are bind on the front end and when back-end is consulted, >> value >>>> in front end are updated and so screen are updated. >>>> (one more time, our code is only a demonstration code to help to find >> the >>>> goods one) >>>> >>>> 80-20 rule is always true, with SPA too >>>> so I'm really confident than 80% of xml screen/menu/form can be renderer >>>> with a SPA and having a very good SPA advantage usage. >>>> For the 20%, it will need to have dedicated SPA component, and during >>>> "migration" process which screen should be in 20% will be discuss. >>>> >>>> Olivier >>>> >>>> >>>> >>>> Le 14/12/2019 à 17:51, Taher Alkhateeb a écrit : >>>>> Hello Gil, >>>>> >>>>> Great research on the subject, thank you for sharing. >>>>> >>>>> I could be wrong here, but at a first glance it seems you want to >>>>> essentially create a tag "<update-area ..." which essentially renders >>>>> another screen dynamically upon clicking / activating the URL. If my >>>>> understanding is correct, then most likely they way you want to >>>>> implement this is probably some web request to the backend which >>>>> renders back a partial screen that you insert into the DOM right? >>>>> >>>>> If what I describe above is close to your idea, then I think the >>>>> implementation might be relying on the server to do the work of >>>>> painting instead of relying on the browser to do the heavy lifting. >>>>> This also only works with one widget, which is the URL widget as >>>>> opposed to having a general purpose dynamic behavior in the system >>>>> (assuming this is desired). >>>>> >>>>> However, having a general purpose dynamic behavior means we need a >>>>> method to bind variables to values at the front end without consulting >>>>> the back-end. This reduces the load on the server and provides a >>>>> faster / richer experience to the user. But it would be too painful to >>>>> rely on plain javascript or jQuery to achieve such a result which is >>>>> the reason why frameworks like React, Vue, and others emerged as >>>>> modern SPA frameworks. Adopting an SPA framework would provide dynamic >>>>> behavior (everywhere) instead of certain widgets, and it can be >>>>> expanded to even include page navigation and whatnot. Of course this >>>>> is more work than what you're suggesting here. but if we continue with >>>>> such small improvements, you might end up having lots of javascript >>>>> (maybe that's already the case) which might increase the difficulty of >>>>> adopting an SPA framework in the future. >>>>> >>>>> So it comes down to this question (which I don't necessarily have an >>>> answer to): >>>>> >>>>> Do you want an SPA framework now or in the future, or do you want to >>>>> continue with status quo into the future? If you want an SPA >>>>> framework, then we should minimize the usage of custom javascript >>>>> everywhere and adopt a framework that completely replaces all the >>>>> javascript that currently exists for all the widgets. If not, then we >>>>> can proceed with your proposition and any others in the future knowing >>>>> that an overhaul is not needed. >>>>> >>>>> Cheers, >>>>> >>>>> Taher Alkhateeb >>>>> >>>>> On Fri, Dec 13, 2019 at 6:52 PM Gil Portenseigne >>>>> <gil.portensei...@nereide.fr> wrote: >>>>>> >>>>>> Chapter One: How to manage the updating area >>>>>> >>>>>> Hello, >>>>>> >>>>>> After different discussions already listed by Taher [1-9], Leila, >>>>>> Nicolas and me tried another approach. >>>>>> Instead of analyzing how to implement different functionalities >> offered >>>>>> by modern js framework, we did analyzed how end user use, in general, >>>>>> OFBiz and where we, as an integrator, waste more time to create a >>>>>> screen. >>>>>> >>>>>> To help on this huge task, we set some basic rules : >>>>>> * Work only on screens supported by the theme, defined mainly in >> xml >>>>>> * This concerns only screens used for back-office applications, >>>>>> oriented to manage data >>>>>> * A developer does not have to know all of js language (or other) >>>>>> but can concentrate on the process/view with the end user to >>>>>> manage a data >>>>>> >>>>>> >>>>>> After a first brainstorm, we have identified three major cases : >>>>>> 1. Navigation and data display >>>>>> 2. View event result (data modification, calculation service, ...) >>>>>> 3. Update an area to refresh data (after data modification) >>>>>> >>>>>> Case 1 and 2 are easy and currently managed by OFBiz (and missing >> stuff >>>>>> will be simple to add), we concentrate our attention on case 3. >>>>>> >>>>>> To update an area, we follow this pattern >>>>>> >>>>>> 1. We start from a context that display different information >>>>>> >>>>>> 2. That context display a submit form, use a link or another >>>>>> mechanism to call an OFBiz event >>>>>> >>>>>> 3. After receiving the event return, we refresh the desired area >>>>>> with parameters that can come from origin context or from event >>>>>> return. >>>>>> >>>>>> >>>>>> Currently with the screen widget, we can use within a form the element >>>>>> `<on-event-update-area event-type="submit" area-id="" >> area-target=""/>`. >>>>>> >>>>>> The problem with this use, is that your form needs to know the origin >>>>>> context, to identify what are the areas to update and what are the >>>>>> target to use for the refresh. >>>>>> >>>>>> So your form needs to know where it comes from, what information need >> to >>>>>> be updated in OFBiz and what will be updated after. >>>>>> >>>>>> This increases complexity for the developer in the way that current >> form >>>>>> implementation manages : >>>>>> * the data and target to communicate with the server >>>>>> * the behaviour (refreshment) to apply when receiving server >> response. >>>>>> >>>>>> Example : >>>>>> <form name="EditPartyRoleCustomScreen" type="single" >>>> target="createPartyRole"> >>>>>> <field name="partyId"><hidden/></field> >>>>>> <field name="roleTypeId">... >>>>>> <on-event-update-area event-type="submit" >>>> area-id="PartyRoles_area" >>>>>> area-target="PartyRolesCustom"> >>>>>> <parameter param-name="partyId" >>>> from-field="parameters.partyId"/> >>>>>> </on-event-update-area> >>>>>> </form> >>>>>> >>>>>> If you want to reuse the same form, you need to create another screen >>>>>> with a new form to redefine the on-event-update-area (for instance >>>>>> create a PartyRole). >>>>>> >>>>>> We change the thinking, because since it is the starting context that >>>>>> better knows itself, it's the starting context that will realize the >>>>>> updating operation. The starting context is the screen/menu that call >>>>>> this form. >>>>>> >>>>>> In general a form is contained in a screen (classic) that is called >>>>>> through a link. So we move the idea on this link : >>>>>> >>>>>> <link target="CreatePartyRole" link-type="layered-modal"> >>>>>> <parameter param-name="partyId" >>>> from-field="customerParty.partyId"/> >>>>>> <update-area area-target="ResumeInfoCustomer" >>>> area-id="xxx"> >>>>>> <parameter param-name="partyId" >>>> from-field="customerParty.partyId"/> >>>>>> </update-area> >>>>>> </link> >>>>>> >>>>>> And the form : >>>>>> >>>>>> <form name="EditPartyRole" type="single" >>>> target="createPartyRole"> >>>>>> <field name="partyId"><hidden/></field> >>>>>> <field name="roleTypeId">... >>>>>> </form> >>>>>> >>>>>> With this logic you can define a new usage of createPartyRole >>>>>> without redefining a form just : >>>>>> >>>>>> <link target="CreatePartyRole" link-type="layered-modal"> >>>>>> <parameter param-name="partyId" >>>> from-field="partyRelationship.partyIdTo"/> >>>>>> <update-area area-target="MyRelationAndDetail" >>>> area-id="xxx"> >>>>>> <parameter param-name="partyId" >>>> from-field="partyRelationship.partyIdTo"/> >>>>>> <parameter param-name="partyRelationTypeId" >>>> value="IRL_LIKE"/> >>>>>> </update-area> >>>>>> </link> >>>>>> >>>>>> After some use we identified as pro and con feedback : >>>>>> * updating form is reusable and contains only code related to the >>>>>> form action >>>>>> * link being in origin context, the developer knows where he is >> and >>>>>> where he wants to go >>>>>> * Menu oriented management offers a quick vision on how the screen >>>> will works >>>>>> >>>>>> * update-area seems to be a too technical name >>>>>> * we always have to manage area to update manually >>>>>> * too many areas to update become a headache and not only for the >>>> developer >>>>>> >>>>>> We did not explain how we have done it, to try to focus the discussion >>>>>> on the principles. >>>>>> >>>>>> It would be a pleasure to have some criticism of this approach, and we >>>>>> would try, in a second chapter to introduce other concepts that >> appeared >>>>>> after the screens were made more dynamic and others to lowers the >>>>>> identified cons. >>>>>> >>>>>> Thanks, >>>>>> >>>>>> The Néréide Team >>>>>> >>>>>> [1] https://s.apache.org/rf94 >>>>>> [2] https://s.apache.org/g5zr >>>>>> [3] https://s.apache.org/XpBO >>>>>> [4] https://s.apache.org/YIL1 >>>>>> [5] https://s.apache.org/836D >>>>>> [6] https://s.apache.org/DhyB >>>>>> [7] https://s.apache.org/Lv9E >>>>>> [8] https://s.apache.org/zKIo >>>>>> [9] https://s.apache.org/D6jx >>>>>> >>>> >>> >> >