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
>>>>>>
>>>>
>>>
>>
> 

Reply via email to