Skip to content

Release Candidate Version 1.1.0 - #204

Open
clauspruefer wants to merge 23 commits into
mainfrom
v1.1.0
Open

Release Candidate Version 1.1.0#204
clauspruefer wants to merge 23 commits into
mainfrom
v1.1.0

Conversation

@clauspruefer

@clauspruefer clauspruefer commented Aug 3, 2026

Copy link
Copy Markdown
Member

Pull Request

Description

Release Candidate v1.1.

  • Add Static / DB-less (100% serverless) component
  • DOM ID Layer handling massively shortened (reduces overall rendering times)
  • Fixed Global Variable Handling / Source Data Handling
  • Add DivUnique, ProgressBar and RangeSlider Object Types
  • Fix Default Loader XMLRPC Type from POST to GET
  • Set Button default type to POST, add RequestMethod Property (object.json) for all Button Types
  • Improve CSS / Bootstrap Styling
  • Documentation Update

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Copilot AI review requested due to automatic review settings August 3, 2026 11:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Release candidate v1.1.0 update that expands the x0 front-end object framework with new UI object types, introduces recursive object data get/set APIs, adjusts XMLRPC request defaults/method handling, and updates examples + documentation accordingly.

Changes:

  • Added recursive getObjectData(recursive) / setObjectData(data, recursive) support in sysBaseObject, plus runnable examples and documentation.
  • Introduced new system objects (DivUnique, ProgressBar, RangeSlider) and updated multiple UI components to use shorter/override ObjectIDs and Bootstrap styling.
  • Updated XMLRPC/button request-method behavior and improved global variable/source-object handling.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
www/sysXMLRPCRequest.js Default XMLRPC request type set to GET; header tweak.
www/sysSourceObjectHandler.js Implements GlobalVar source object resolution via factory global vars.
www/sysObjTreeSimple.js Refactors tree DOM structure/styling to Bootstrap list groups; ID handling changes.
www/sysObjTabContainer.js Adjusts ObjectID overriding/initialization for tab container.
www/sysObjSQLText.js Tweaks icon postfix HTML spacing.
www/sysObjRangeSlider.js New RangeSlider system object.
www/sysObjProgressBar.js New ProgressBar system object.
www/sysObjOpenCloseContainer.js ObjectID override + header uses sysObjSQLText (icon/text).
www/sysObjList.js ObjectID override/uniqueness changes.
www/sysObjFormfieldList.js ObjectID override + mapping support in setData; validation flow adjustments.
www/sysObjFormfieldItem.js Formatting/field alignment changes.
www/sysObjFileUpload.js Ensures ObjectID set; minor formatting fix.
www/sysObjDiv.js Formatting updates + new sysObjDivUnique.
www/sysObjContextMenu.js Refactors context menu rendering to Bootstrap list-group; adds hover highlighting.
www/sysObjButtonInternal.js ObjectID override + constructor field refactor/commenting.
www/sysObjButtonCallback.js ObjectID override + constructor refactor/commenting.
www/sysObjButton.js Adds RequestMethod handling and new actions (set, setglobalvar); action flow changes.
www/sysFormfieldValidate.js Updates group validation to use UserValidateGroup.
www/sysFactory.js Registers new object types + adds setGlobalVar.
www/sysBaseObject.js Adds recursive object data get/set helpers + wrapper signature changes.
www/sysAsyncNotifyIndicatorItem.js CSS class tweak for notify indicator items.
static/sysInitOnLoad.js New static (DB-less) initialization entrypoint.
example/recursive_object_data/recursive_object_data_examples.js New console examples covering recursive get/set scenarios.
example/recursive_object_data/README.md Documentation for recursive object data examples.
example/README.md Links new recursive object data example.
doc/dev-oop-classes.rst Documents recursive get/set API and updates section numbering.
Suppressed comments (1)

www/sysObjButton.js:373

  • Similar to the set branch, the append branch calls RuntimeAppendDataFunc unconditionally after re-fetching objects without guarding against missing IDs or missing function pointers. This can throw and break button actions at runtime.
        else if (Action == 'append') {
            const SrcObject = sysFactory.getObjectByID(Attributes.SrcDataObject);
            const DstObject = sysFactory.getObjectByID(Attributes.DstDataObject);
            DstObject.RuntimeAppendDataFunc(SrcObject.RuntimeGetDataFunc());
        }

Comment thread www/sysFormfieldValidate.js
Comment thread www/sysObjButton.js
Comment thread www/sysObjProgressBar.js
Comment thread www/sysObjContextMenu.js Outdated
Comment thread www/sysObjFormfieldList.js Outdated
Comment thread www/sysObjFormfieldList.js
Comment thread static/sysInitOnLoad.js Outdated
@clauspruefer

clauspruefer commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

@copilot please propose a refactoring regarding the button action handling (processActions() and callbackXMLRPCAsync()) in sysObjButton.js, sysObjButtonInternal.js and sysObjButtonCallback.js. Currently processActions() and callbackXMLRPCAsync() use different processing, where it should be one single processing. Also the processing is quite NON-OOP and could be handled outside by one more OOP centric design.

Copilot AI commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@copilot please propose a refactoring regarding the button action handling (processActions() and callbackXMLRPCAsync()) in sysObjButton.js, sysObjButtonInternal.js and `sysObjButtonCallback.js...

Here is the proposed refactoring.

Problem

The current design has three issues:

  1. Duplicated action dispatchprocessActions() and callbackXMLRPCAsync() each contain their own if/else chains that map action name strings ('enable', 'disable', 'activate', 'deactivate', 'reset', etc.) to object calls, with subtle differences between them.
  2. No OOP boundary – All action logic lives inline inside the button methods; there is no encapsulated object responsible for "executing an action on a target object".
  3. Inconsistency across button typessysObjButtonInternal copies processActions by prototype reference; sysObjButtonCallback does not need it at all. A shared base class or mixin would be cleaner.

Proposed Design

1. Introduce sysButtonActionProcessor (new file sysButtonActionProcessor.js)

A single class owns all action-to-method dispatch. Both the pre-RPC path and the post-RPC callback path delegate to it.

// sysButtonActionProcessor.js

function sysButtonActionProcessor() {}

// Core dispatcher: executes one action descriptor { Action, DstObjectID, ... }
sysButtonActionProcessor.prototype.executeAction = function(ActionConf) {
    const Action = (ActionConf.Action || '').toLowerCase();
    if (!Action) return;

    let DstObject;
    try {
        DstObject = sysFactory.getObjectByID(ActionConf.DstObjectID);
    } catch(e) {
        DstObject = undefined;
    }

    switch (Action) {

        case 'set':
            try {
                const Src = sysFactory.getObjectByID(ActionConf.SrcDataObject);
                const Dst = sysFactory.getObjectByID(ActionConf.DstDataObject);
                Dst.RuntimeSetDataFunc(Src.RuntimeGetDataFunc());
            } catch(e) {
                console.debug('::executeAction set error:%s', e);
            }
            break;

        case 'append':
            try {
                const Src = sysFactory.getObjectByID(ActionConf.SrcDataObject);
                const Dst = sysFactory.getObjectByID(ActionConf.DstDataObject);
                Dst.RuntimeAppendDataFunc(Src.RuntimeGetDataFunc());
            } catch(e) {
                console.debug('::executeAction append error:%s', e);
            }
            break;

        case 'enable':
            if (DstObject) { DstObject.VisibleState = 'visible'; DstObject.setDOMVisibleState(); }
            break;

        case 'disable':
            if (DstObject) { DstObject.VisibleState = 'hidden'; DstObject.setDOMVisibleState(); }
            break;

        case 'activate':
            if (DstObject) { DstObject.setActivated(); }
            break;

        case 'deactivate':
            if (DstObject) { DstObject.setDeactivated(); }
            break;

        case 'reset':
            if (DstObject) { DstObject.reset(); }
            break;

        case 'tabswitch':
            try {
                const TabContainer = sysFactory.getObjectByID(ActionConf.TabContainer);
                TabContainer.switchTab(ActionConf.Tab);
            } catch(e) {
                console.debug('::executeAction tabswitch error:%s', e);
            }
            break;

        case 'switchscreen':
            sysFactory.switchScreen(ActionConf.DstScreenID);
            break;

        case 'setglobalvar':
            sysFactory.setGlobalVar(ActionConf.SetVar, ActionConf.SetValue);
            break;

        default:
            console.debug('::executeAction unknown action:%s', Action);
    }
};

// Execute a list of action descriptors (array or single object)
sysButtonActionProcessor.prototype.executeActions = function(ActionConf) {
    if (!ActionConf) return;
    const Actions = Array.isArray(ActionConf) ? ActionConf : [ActionConf];
    for (const A of Actions) {
        this.executeAction(A);
    }
};

// Shared singleton – one instance used by all button types
const sysButtonActions = new sysButtonActionProcessor();

2. Simplify sysObjButton.prototype.processActions

The method becomes a thin wrapper that normalises the attribute shape and delegates:

sysObjButton.prototype.processActions = function() {
    const Attributes = this.JSONConfig.Attributes;

    // Build a single action descriptor from the flat Attributes shape
    // (pre-RPC actions use Action / DstObjectID / SrcDataObject / DstDataObject / …)
    const ActionConf = Object.assign({ Action: Attributes.Action }, Attributes);
    sysButtonActions.executeAction(ActionConf);

    // Screen switch with optional ResetAll
    if (this.DstScreenID !== undefined) {
        if (Attributes.ResetAll === true) {
            sysFactory.getScreenByID(this.DstScreenID).HierarchyRootObject.processReset();
        }
        sysFactory.switchScreen(this.DstScreenID);
    }

    // Fire events
    if (Attributes.FireEvents !== undefined) {
        sysFactory.Reactor.fireEvents(Attributes.FireEvents);
    }

    // Close overlay
    if (Attributes.CloseOverlay === true) {
        try { sysFactory.OverlayObj.EventListenerClick(); } catch(e) {}
    }
};

3. Simplify sysObjButton.prototype.callbackXMLRPCAsync

The OnResult loop now delegates to the same processor:

sysObjButton.prototype.callbackXMLRPCAsync = function() {
    const MsgHandler = sysFactory.sysGlobalAsyncNotifyHandler;
    let NotifyStatus = 'ERROR';

    if (this.XMLRPCResultData.ErrorCode === undefined && this.XMLRPCResultData.error === undefined) {
        const Attributes = this.JSONConfig.Attributes;

        // Post-RPC actions (OnResult list)
        sysButtonActions.executeActions(Attributes.OnResult);

        // Screen / tab switch
        if (Attributes.SwitchScreen) {
            sysFactory.switchScreen(Attributes.SwitchScreen);
        }
        if (Attributes.SwitchTabContainer !== undefined && Attributes.SwitchTabID !== undefined) {
            sysFactory.getObjectByID(Attributes.SwitchTabContainer)
                      .TabContainerObject.switchTab(Attributes.SwitchTabID);
        }

        // Fire events
        if (Attributes.FireEvents !== undefined) {
            sysFactory.Reactor.fireEvents(Attributes.FireEvents);
        }

        this.fireNetEvents();
        NotifyStatus = 'SUCCESS';
    }

    try {
        const IndicatorID = this.JSONConfig.Attributes.Notify.ID;
        if (IndicatorID !== undefined) {
            MsgHandler.processMsg({
                'msg-type': 'sys-indicator',
                'notify-id': IndicatorID,
                'notify-status': NotifyStatus
            });
        }
    } catch(e) {
        console.log('err:%s', e);
    }
};

4. Clean up sysObjButtonInternal

Because processActions is now on the shared prototype chain via sysObjButton, sysObjButtonInternal no longer needs to copy it explicitly. It simply inherits from sysObjButton (or keeps its current prototype but drops the redundant line):

// remove: sysObjButtonInternal.prototype.processActions = sysObjButton.prototype.processActions;

Summary of changes

File Change
sysButtonActionProcessor.js New – single-responsibility action dispatcher
sysObjButton.js processActions and callbackXMLRPCAsync become thin wrappers delegating to sysButtonActions.executeAction(s)
sysObjButtonInternal.js Remove the copied processActions reference; inherits the simplified version
sysObjButtonCallback.js No change needed (does not use action processing)

This makes the action dispatch testable in isolation, DRY across the pre- and post-RPC paths, and easy to extend (add a new action type in one place).

Let me know if you'd like me to implement these changes directly in the files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants