Files
skidus f705cd11b9 feat: implement advanced bidirectional field referencing and cross-module path resolution
- Core Logic Enhancements:
    - Implement bidirectional field referencing between <FIELDS>, <LAYOUT>, and <TITLES> tags in .frml files, enabling seamless navigation from definitions to usages and vice versa.
    - Add robust support for AJAX-OPTION field mapping:
        - SRC attribute: Links to field definitions within defs/ajax.xml datasets.
        - TARGET attribute: Links to local field definitions within the same form.
    - Implement global grid resolution: GRID-ID now searches across the current file and all recursively included files (<INCLUDE>).
    - Enhance deep recursive search for fields/sections within nested tags like <SECTION>, <ROW>, and <FIELD-LIST>.

- Path Resolution & Helpers (DynFormPathUtils):
    - Added support for module-relative paths starting with # (mapping to view/frm/).
    - Added support for cross-module paths starting with / (mapping to WEB-INF/app/module/{module}/view/frm/).
    - Implemented auto-correction for common keyboard typos (Thai 'ิ' instead of /).
    - Added specialized helpers for locating ajax.xml and included files within the framework's structure.

- Smart Completion Enhancements:
    - Added context-aware completion for TARGET and SRC fields in AJAX update-fields.
    - Enabled global GRID-ID completion by scanning all included resources.
    - Improved dataset completion to include both local and AJAX-defined datasets.

- Test Resources:
    - Added a comprehensive set of real-world examples (bdgt04, bdgt05, bdgt06) in DevResources/full-examples/ to validate complex cross-module and master-detail scenarios.
2026-04-10 12:56:04 +07:00

113 lines
4.5 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<FORMS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/#dynf_form_def.xsd">
<DATASETS>
<DATASET ID="DS-MASTER">
<SCHEMA>APP</SCHEMA>
<TABLENAME>PROJECTS</TABLENAME>
<KEYFIELDS>PROJ_ID</KEYFIELDS>
<SQL>
<SELECT>SELECT PROJ.PROJ_ID
, PROJ.PROJ_TYPE
, PROJ.PROJ_YEAR
, PROJ.STM_CODE
, PROJ.FLOW_TYPE
, PROJ.FLOW_TYPE_DESC
, PROJ.PJM_CODE, PROJ.PROJ_NAME
, PROJ.ACM_CODE, PROJ.ACM_NAME
, PROJ.PROJ_SEQ
, (SELECT RFC_DESC FROM REFER_CODE RFC WHERE RFC.RFG_GRP='FLOW-STATE' AND RFC.RFC_CODE='REVISE') FLOW_STATE
</SELECT>
<FROM>
FROM (SELECT PROJ.PROJ_ID
, PROJ.PROJ_TYPE
, TO_CHAR(PROJ.PROJ_YEAR, 'FM0000') PROJ_YEAR
, PROJ.STM_CODE
, FTYP.RFC_CODE FLOW_TYPE
, FTYP.RFC_DESC FLOW_TYPE_DESC
, PROJ.PJM_CODE, BUD.GET_PROJECT(PROJ.PJM_CODE) PROJ_NAME
, PROJ.ACM_CODE, BUD.GET_ACTIVITY(PROJ.ACM_CODE) ACM_NAME
, FTYP.RFC_ORDER PROJ_SEQ
FROM REFER_CODE FTYP
INNER JOIN REFER_CODE PTYPE ON PTYPE.RFG_GRP = 'PROJ-TYPE' AND PTYPE.RFC_FLAG = FTYP.RFC_CODE
INNER JOIN PROJECTS PROJ ON PROJ.PROJ_TYPE = PTYPE.RFC_CODE
WHERE FTYP.RFG_GRP = 'FLOW-TYPE' AND FTYP.RFC_CODE != 'GENERAL' AND PROJ.PROJ_YEAR = :PROJ_YEAR AND PROJ.STM_CODE = :STM_CODE
UNION ALL
SELECT :PROJ_YEAR || 'xGENERALx' || :STM_CODE PROJ_ID
, 'GENERAL' PROJ_TYPE
, :PROJ_YEAR PROJ_YEAR
, :STM_CODE STM_CODE
, FTYP.RFC_CODE FLOW_TYPE
, FTYP.RFC_DESC FLOW_TYPE_DESC
, 'GENERAL' PJM_CODE, FTYP.RFC_DESC PROJ_NAME
, 'GENERAL' ACM_CODE, FTYP.RFC_DESC ACM_NAME
, FTYP.RFC_ORDER PROJ_SEQ
FROM REFER_CODE FTYP
WHERE FTYP.RFC_CODE = 'GENERAL'
) PROJ
</FROM>
<ORDER>ORDER BY PROJ_SEQ, PROJ_ID</ORDER>
</SQL>
</DATASET>
</DATASETS>
<FORM>
<FORM_BROWSE DATAID="DS-MASTER">
<HEADER NAVI="N" EDIT="N" ADD="N" DELETE="N" VIEW="N"/>
<PAGESIZE>0</PAGESIZE>
<FIELDS>
<FIELD NAME="$itemno" LABEL="no" ALIGN="right" WIDTH="5em"/>
<FIELD NAME="FLOW_TYPE_DESC" LABEL="props.type" ALIGN="left" WIDTH="20em">
<DATA-FORMATTER>
<![CDATA[(value,row,idx)=>{return $(`<div class="col-24 text-nowrap"><div class="col offset-${+(row.node_level)-1}">${value}</div></div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="PROJ_NAME" LABEL="project.const_name" ALIGN="left">
<DATA-FORMATTER>
<![CDATA[(value,row,idx)=>{return $(`<div class="col-24 row"><div class="col offset-${+(row.node_level)-1}">${value}</div></div>`);}]]>
</DATA-FORMATTER>
</FIELD>
<FIELD NAME="FLOW_STATE" LABEL="props.state" ALIGN="center" WIDTH="10em"/>
<COMMAND-BUTTONS>
<BUTTON NAME="btnEditor" CLASS="btn btn-warning btn-editor" ICON-CLASS="fa fa-edit white">
<EVENT ON="click"><![CDATA[
({ev,row})=>{
console.log(row);
row.pageTitle = $("h4.page-title").html();
if (row.proj_type === "GENERAL") {
$PageCtx.saveSessionData("general", row);
$PageCtx.saveStorageData("general#search", {proj_year: row.proj_year});
$WebNavi.goto("/bdgt04/bgt0403010-general");
} else {
$PageCtx.saveSessionData("project", row);
let proj = {proj_id : row.proj_id,acm_code : row.acm_code, type: row.proj_type.toLowerCase()};
let data = base64(JSON.stringify(proj)) ;
let editUrl = `/bdgt04/bgt0403010-project?edit&data=${data}`;
$WebNavi.goto(editUrl);
}
}
]]></EVENT>
</BUTTON>
<BUTTON NAME="btnViewer" CLASS="btn btn-primary btn-viewer" ICON-CLASS="fa fa-file-alt white">
<EVENT ON="click"><![CDATA[({ev,row})=>{ console.log(row);}]]></EVENT>
</BUTTON>
</COMMAND-BUTTONS>
</FIELDS>
<FILTERS AUTO-APPLY="Y" ALLOW-NO-FILTER="Y">
<FIELDS>
<FIELD NAME="PROJ_YEAR" CAPTION="project.year" INPUTTYPE="COMBOBOX" SEARCH-ORIGIN="PROJ_YEAR=${VALUE}">
<LIST-OPTION TABLE="VL_YEAR" TEXT="#DV_YEAR" VALUE="DV_YEAR" ORDER="DV_YEAR" FIRSTLIST="@{NONE}"/>
</FIELD>
<FIELD NAME="VERSION" CAPTION="props.versions" INPUTTYPE="COMBOBOX">
<LIST-OPTION TABLE="REFER_CODE" TEXT="#RFC_DESC" VALUE="RFC_CODE" ORDER="RFC_ORDER" FILTER="RFG_GRP='PROPS-VERS'" FIRSTLIST="@{NONE}"/>
</FIELD>
</FIELDS>
<LAYOUT>
<ROW>
<FIELD NAME="PROJ_YEAR" VAL_WIDTH="6" CAPT_WIDTH="12" LAYOUT_WIDTH="12"/>
</ROW>
</LAYOUT>
</FILTERS>
</FORM_BROWSE>
</FORM>
</FORMS>