@xuda.io/runtime-bundle 1.0.1152 → 1.0.1154

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32685,7 +32685,2219 @@ func.UI.screen.execute_xu_functions = async function (SESSION_ID, is_skeleton, $
32685
32685
  SESSION_ID,
32686
32686
  cond,
32687
32687
  paramsP.dsSessionP,
32688
- func.UI.component = {};
32688
+ 'UI Attr EXP',
32689
+ $elm.data().xuData.currentRecordId, // SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId
32690
+ null,
32691
+ null,
32692
+ null,
32693
+ null,
32694
+ null,
32695
+ $elm.data().xuData.iterate_info,
32696
+ );
32697
+
32698
+ if (res.result) {
32699
+ $elm.addClass(cla);
32700
+ } else {
32701
+ $elm.removeClass(cla);
32702
+ }
32703
+
32704
+ $elm.data().xuData.debug_info.attribute_stat['xu-class'] = $elm.attr('class');
32705
+ }
32706
+ return {};
32707
+ } catch (e) {
32708
+ console.warn('parse error:' + val.value);
32709
+ return { abort: true };
32710
+ }
32711
+ },
32712
+ 'xu-exp': async function ($elm, val) {
32713
+ let exp = val.value === null ? true : val.value;
32714
+
32715
+ let exp_ret = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP].currentRecordId, null, null, null, null, null, $elm.data().xuData.iterate_info);
32716
+
32717
+ let value = func.UI.screen.fix_val_defaults(val.key, exp_ret.result);
32718
+
32719
+ var new_val = {
32720
+ key: val.key,
32721
+ value,
32722
+ };
32723
+
32724
+ if (nodeP.tagName.substr(0, 3) === 'xu-') {
32725
+ if (tag_fx[nodeP.tagName][new_val.key]) {
32726
+ return await tag_fx[nodeP.tagName][new_val.key]($elm, new_val);
32727
+ }
32728
+ console.warn(`attribute ${new_val.key} not found for ${nodeP.tagName}`);
32729
+ return {};
32730
+ }
32731
+ if (!$elm.data().xuData) return;
32732
+
32733
+ $elm.data().xuData.debug_info.attribute_stat[new_val.key] = new_val.value;
32734
+
32735
+ // IGNORE UNDEFINED or NULL ATTRIBUTES
32736
+ if (typeof new_val.value === 'undefined' || new_val.value === null) {
32737
+ return {};
32738
+ }
32739
+
32740
+ // IGNORE ATTRIBUTES WITH EMPTY VALUES
32741
+ if (glb.solid_attributes.includes(new_val.key) && !new_val.value) {
32742
+ return {};
32743
+ }
32744
+
32745
+ if (new_val.key.substr(0, 2) === 'xu') {
32746
+ return await common_fx[new_val.key]($elm, new_val);
32747
+ }
32748
+
32749
+ $elm.attr(new_val.key, ($elm.attr(new_val.key) || '') + new_val.value);
32750
+ return {};
32751
+ },
32752
+ 'xu-on': async function ($elm, val) {
32753
+ CLIENT_ACTIVITY_TS = Date.now();
32754
+ const trigger = val.key.split('xu-on:')[1].toLowerCase();
32755
+ $elm.on(trigger, async function (evt) {
32756
+ const _$elm = $(evt.currentTarget);
32757
+ if (_.isEmpty(_$elm.data().xuAttributes)) return;
32758
+
32759
+ for await (const [key, val] of Object.entries(_$elm.data().xuAttributes['xu-on:' + evt.type])) {
32760
+ if (!_.isEmpty(val.props.condition)) {
32761
+ const expCond = await func.expression.get(SESSION_ID, val.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
32762
+ if (!expCond.result) continue;
32763
+ }
32764
+
32765
+ if (val.event_modifiers && evt[val.event_modifiers]) {
32766
+ evt[val.event_modifiers]();
32767
+ }
32768
+
32769
+ // if (val.handler === 'custom') {
32770
+ if (val.workflow) {
32771
+ // do BL
32772
+ for await (const [key2, val2] of Object.entries(val.workflow)) {
32773
+ // var cond = val2.data.enabled;
32774
+ // if (val2.data.enabled && val2.props.condition) {
32775
+ // expCond = await func.expression.get(SESSION_ID, val2.props.condition, paramsP.dsSessionP, 'condition', paramsP.recordid); // execute expression
32776
+ // cond = expCond.result;
32777
+ // }
32778
+ // if (!cond) continue;
32779
+
32780
+ if (!val2.data.enabled) continue; // added Jul 3, 25 - condition validate on execution
32781
+
32782
+ func.events.add_to_queue(SESSION_ID, 'element event', val2.id, evt.type, val2.data.action, val2.data.name, null, _$elm.attr('xu-ui-id'), null, evt, null, null, null, paramsP.dsSessionP, null, null, null, evt.type, val2.data.name, null, null, val2, null, null, null, null, null, null);
32783
+ }
32784
+ }
32785
+ }
32786
+ });
32787
+ return {};
32788
+ },
32789
+ 'xu-script': async function ($elm, val) {
32790
+ var checkExist = setInterval(async function () {
32791
+ if ($elm.is(':visible')) {
32792
+ try {
32793
+ // var res = eval('(' + val.value + ')');
32794
+ // const fn = `(function(el) {
32795
+ // ${val.value}
32796
+ // })(document.querySelector(\`[xu-ui-id="${$elm.attr('xu-ui-id')}"]\`));`;
32797
+
32798
+ const fn = `async (el)=>{${val.value} };`;
32799
+
32800
+ var res = eval(fn);
32801
+ await res($elm[0]);
32802
+ // if (typeof res === 'function') {
32803
+ // res($elm[0]);
32804
+ // }
32805
+ } catch (e) {
32806
+ eval(val.value);
32807
+ }
32808
+
32809
+ clearInterval(checkExist);
32810
+ }
32811
+ }, 100); // check every 100ms
32812
+
32813
+ return {};
32814
+ },
32815
+ 'xu-style-global': async function ($elm, val) {
32816
+ $('head').append(`<style>${val.value}</style>`);
32817
+ return {};
32818
+ },
32819
+ 'xu-style': async function ($elm, val) {
32820
+ var cssString = val.value;
32821
+
32822
+ var parser = new cssjs();
32823
+
32824
+ var parsed = parser.parseCSS(cssString);
32825
+ var xuUiId = `[xu-ui-id="${$elm.attr('xu-ui-id')}"]`;
32826
+
32827
+ $.each(parsed, function (key, val) {
32828
+ var selectors_arr = val.selector.split(',');
32829
+
32830
+ $.each(selectors_arr, function (key2, val2) {
32831
+ selectors_arr[key2] = `${xuUiId} ${val2}, ${xuUiId}${val2}`;
32832
+ // console.log(new_selector);
32833
+ });
32834
+
32835
+ val.selector = selectors_arr.join(',');
32836
+ // console.log(parsed);
32837
+ });
32838
+
32839
+ var newCSSString = parser.getCSSForEditor(parsed);
32840
+
32841
+ $('head').append(`<style>${newCSSString}</style>`);
32842
+ return {};
32843
+ },
32844
+ 'xu-cdn': async function ($elm, val) {
32845
+ for await (const [key, resource] of Object.entries(val.value)) {
32846
+ await load_cdn(resource);
32847
+ }
32848
+
32849
+ return {};
32850
+ },
32851
+ 'xu-ui-plugin': async function ($elm, val) {
32852
+ var _session = SESSION_OBJ[SESSION_ID];
32853
+
32854
+ for await (const [plugin_name, value] of Object.entries(val.value)) {
32855
+ const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
32856
+ if (_plugin?.installed && _plugin?.manifest?.['runtime.mjs']?.exist && _plugin?.manifest?.['index.mjs']?.exist && value.enabled) {
32857
+ if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
32858
+ const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
32859
+ func.utils.load_css_on_demand(plugin_runtime_css_url);
32860
+ }
32861
+
32862
+ const plugin_index_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
32863
+
32864
+ const plugin_index_resources = await import(plugin_index_src);
32865
+
32866
+ let properties = _.cloneDeep(plugin_index_resources.properties);
32867
+ for await (let [prop_name, prop_val] of Object.entries(properties)) {
32868
+ prop_val.value = value?.attributes?.[prop_name];
32869
+ if (value?.attributes?.[`xu-exp:${prop_name}`]) {
32870
+ const res = await func.expression.get(SESSION_ID, value?.attributes?.[`xu-exp:${prop_name}`], paramsP.dsSessionP, 'UI Attr EXP');
32871
+ prop_val.value = res.result;
32872
+ }
32873
+ }
32874
+ // $elm.data().xu_ui_plugin = { properties };
32875
+ const plugin_runtime_src = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
32876
+
32877
+ const plugin_runtime_resources = await import(plugin_runtime_src);
32878
+
32879
+ if (plugin_runtime_resources.cdn && typeof _.isArray(plugin_runtime_resources.cdn)) {
32880
+ for await (const resource of plugin_runtime_resources.cdn) {
32881
+ await load_cdn(resource);
32882
+ }
32883
+ }
32884
+
32885
+ if (plugin_runtime_resources.fn) {
32886
+ await plugin_runtime_resources.fn(plugin_name, $elm?.[0], properties);
32887
+ // await plugin_runtime_resources.fn(plugin_name, $elm?.[0], $elm.data().xu_ui_plugin.properties);
32888
+ }
32889
+ }
32890
+ }
32891
+
32892
+ return {};
32893
+ },
32894
+ 'xu-store': async function ($elm, val) {
32895
+ try {
32896
+ const fields_obj = JSON5.parse(val.value);
32897
+ for (const [field_id, value] of Object.entries(fields_obj)) {
32898
+ func.datasource.add_dynamic_field_to_ds(SESSION_ID, paramsP.dsSessionP, field_id, value);
32899
+ }
32900
+ } catch (err) {
32901
+ console.error(err);
32902
+ }
32903
+ return {};
32904
+ },
32905
+ 'xu-viewport': async function ($elm, val) {
32906
+ // functionality in draw_html_element
32907
+ return {};
32908
+ },
32909
+ };
32910
+
32911
+ if (nodeP.tagName.substr(0, 3) === 'xu-') {
32912
+ if (xu_func === 'xu-exp') {
32913
+ return common_fx[xu_func]($elm, val);
32914
+ }
32915
+
32916
+ if (tag_fx?.[nodeP.tagName]?.[xu_func]) {
32917
+ let ret = await tag_fx[nodeP.tagName][xu_func]($elm, val);
32918
+ return ret;
32919
+ }
32920
+ // if (xu_func !== "tree_id")
32921
+ console.warn(`attribute ${xu_func} not found for ${nodeP.tagName}`);
32922
+ return {};
32923
+ }
32924
+ if (_.isEmpty($elm.data())) {
32925
+ return {};
32926
+ }
32927
+ if (!$elm.data().xuData.debug_info.attribute_stat) {
32928
+ $elm.data().xuData.debug_info.attribute_stat = {};
32929
+ }
32930
+ if (xu_func !== 'xu-exp') {
32931
+ $elm.data().xuData.debug_info.attribute_stat[xu_func] = val.value;
32932
+ }
32933
+ try {
32934
+ if (!common_fx[xu_func]) {
32935
+ console.warn('invalid xu-tag', xu_func, error);
32936
+ return {};
32937
+ }
32938
+
32939
+ return await common_fx[xu_func]($elm, val);
32940
+ } catch (error) {
32941
+ debugger;
32942
+ }
32943
+ };
32944
+
32945
+ func.UI.screen.fix_val_defaults = function (key, val) {
32946
+ var ret = val;
32947
+ if (
32948
+ key === 'xu-render' &&
32949
+ (typeof val === 'undefined' || val === null || val === '') //|| val === ""
32950
+ ) {
32951
+ // ret = 'Y'; // was ret = "N";
32952
+ ret = true;
32953
+ }
32954
+ if (
32955
+ key === 'xu-show' &&
32956
+ (typeof val === 'undefined' || val === null || val === '') //|| val === ""
32957
+ ) {
32958
+ // ret = 'Y';
32959
+ ret = true;
32960
+ }
32961
+ return ret;
32962
+ };
32963
+
32964
+ func.UI.screen.set_attributes_new = async function (SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $elm, is_init, execute_attributes = [], refreshed_ds) {
32965
+ var done_exp = [];
32966
+
32967
+ const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
32968
+ if (!_ds) return { abort: true };
32969
+
32970
+ const get_attr_value = async function (key) {
32971
+ let ret = func.UI.screen.fix_val_defaults(key, nodeP.attributes[key]);
32972
+ if (nodeP?.attributes?.hasOwnProperty(`xu-exp:${key}`)) {
32973
+ ret = await get_xuExp(key);
32974
+ }
32975
+ return ret;
32976
+ };
32977
+
32978
+ const get_xuExp = async function (attrib) {
32979
+ if (is_skeleton) return;
32980
+ if (glb.new_xu_render) {
32981
+ let _xuData = $elm.data().xuData;
32982
+ if (!_xuData.attr_exp_info) {
32983
+ _xuData.attr_exp_info = {};
32984
+ }
32985
+ }
32986
+ const attr = `xu-exp:${attrib}`;
32987
+
32988
+ if (!nodeP?.attributes?.hasOwnProperty(attr)) return;
32989
+ // const attr = `xu-exp-${attrib}`;
32990
+ var exp = nodeP.attributes[attr];
32991
+ // if (!value) return func.UI.screen.fix_val_defaults(attrib, exp || nodeP.attributes[attrib]);
32992
+
32993
+ var res = await func.expression.get(SESSION_ID, exp, paramsP.dsSessionP, 'UI Attr EXP', _ds.currentRecordId);
32994
+ if (glb.new_xu_render) {
32995
+ _xuData.attr_exp_info[attrib] = res;
32996
+ }
32997
+ // nodeP.attributes[attr] = value; //{ value: value, res: res };
32998
+ done_exp.push(attr);
32999
+ return res.result; //func.UI.screen.fix_val_defaults(attrib, res.result);
33000
+ };
33001
+
33002
+ var _ret = {};
33003
+ if (nodeP.type !== 'element' || !nodeP.attributes) return _ret;
33004
+
33005
+ for (let [key, val] of Object.entries(nodeP.attributes)) {
33006
+ // REMOVE STATIC ATTRIBUTES IF EXP EXISTS to avoid dup
33007
+ if (key.substring(0, 6) === 'xu-exp') {
33008
+ if (_.isEmpty(val)) {
33009
+ delete nodeP.attributes[key];
33010
+ continue;
33011
+ }
33012
+ const clean_key = key.split(':')[1];
33013
+ if (typeof nodeP.attributes[clean_key] !== 'undefined') {
33014
+ delete nodeP.attributes[clean_key];
33015
+ }
33016
+ }
33017
+ // FIX abbreviations
33018
+ if (glb.attr_abbreviations_arr.includes(key)) {
33019
+ nodeP.attributes[`xu-on:${key.substring(3)}`] = [
33020
+ {
33021
+ handler: 'custom',
33022
+ props: {},
33023
+ event: [
33024
+ {
33025
+ id: Date.now(),
33026
+ data: {
33027
+ action: 'update',
33028
+ name: { value: val },
33029
+ enabled: true,
33030
+ },
33031
+ props: {},
33032
+ },
33033
+ ],
33034
+ },
33035
+ ];
33036
+ delete nodeP.attributes[key];
33037
+ }
33038
+ }
33039
+
33040
+ for (let [key, val] of Object.entries(nodeP.attributes)) {
33041
+ // FIX STATIC DEFAULTS
33042
+ val = func.UI.screen.fix_val_defaults(key, val);
33043
+
33044
+ // REMOVE UNDEFINED or NULL ATTRIBUTES
33045
+ if (typeof val === 'undefined' || val === null) {
33046
+ delete nodeP.attributes[key];
33047
+ }
33048
+
33049
+ // REMOVE ATTRIBUTES WITH EMPTY VALUES
33050
+ if (glb.solid_attributes.includes(key) && !val) {
33051
+ delete nodeP.attributes[key];
33052
+ }
33053
+ }
33054
+
33055
+ // XU-ATTRS
33056
+ if (nodeP?.attributes?.['xu-attrs'] || nodeP?.attributes?.['xu-exp:xu-attrs']) {
33057
+ const attr = 'xu-attrs';
33058
+ let ret = await func.UI.screen.execute_xu_functions(
33059
+ SESSION_ID,
33060
+ is_skeleton,
33061
+ $root_container,
33062
+ nodeP,
33063
+ $container,
33064
+ paramsP,
33065
+ parent_infoP,
33066
+ jobNoP,
33067
+ keyP,
33068
+ parent_nodeP,
33069
+ attr,
33070
+ $elm,
33071
+ {
33072
+ key: attr,
33073
+ value: await get_attr_value(attr),
33074
+ },
33075
+ is_init,
33076
+ );
33077
+ }
33078
+
33079
+ // BEFORE
33080
+ if (!_.isEmpty(nodeP.attributes)) {
33081
+ for await (const [key, attr] of Object.entries(glb.run_xu_before)) {
33082
+ if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
33083
+ if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) {
33084
+ continue;
33085
+ }
33086
+
33087
+ if (!nodeP?.attributes?.hasOwnProperty(attr) && !nodeP?.attributes?.hasOwnProperty(`xu-exp:${attr}`)) {
33088
+ continue;
33089
+ }
33090
+
33091
+ if (!nodeP.attributes[`xu-exp:${attr}`] && nodeP?.attributes?.hasOwnProperty(attr) && typeof func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]) === 'undefined') {
33092
+ continue;
33093
+ }
33094
+
33095
+ let ret = await func.UI.screen.execute_xu_functions(
33096
+ SESSION_ID,
33097
+ is_skeleton,
33098
+ $root_container,
33099
+ nodeP,
33100
+ $container,
33101
+ paramsP,
33102
+ parent_infoP,
33103
+ jobNoP,
33104
+ keyP,
33105
+ parent_nodeP,
33106
+ attr,
33107
+ $elm,
33108
+ {
33109
+ key: attr,
33110
+
33111
+ value: await get_attr_value(attr),
33112
+ },
33113
+ is_init,
33114
+ );
33115
+ _ret = _.assignIn(_ret, ret);
33116
+ }
33117
+ }
33118
+
33119
+ // ALL
33120
+
33121
+ for await (const [key, val] of Object.entries(nodeP.attributes)) {
33122
+ if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
33123
+ if (glb.html5_events_handler.includes(key) || execute_attributes.includes(key)) {
33124
+ continue;
33125
+ }
33126
+
33127
+ const new_key = key.split(':')[0]; // break expression
33128
+ if (
33129
+ nodeP.tagName !== 'xu-panel' &&
33130
+ nodeP.tagName !== 'xu-teleport' && // nodeP.tagName.substr(0, 3) !== "xu-" &&
33131
+ (new_key.substr(0, 2) !== 'xu' || new_key.substr(2, 1) !== '-')
33132
+ ) {
33133
+ // handle common html attributes
33134
+ try {
33135
+ $elm.get(0).setAttribute(key, val);
33136
+ } catch (err) {
33137
+ console.error(err.message);
33138
+ }
33139
+
33140
+ continue;
33141
+ }
33142
+ // handle xu attributes
33143
+ try {
33144
+ if ($elm?.data()?.xuAttributes) {
33145
+ // in some cases xu data delete in purpose when refreshing the screen
33146
+ $elm.data().xuAttributes[key] = val;
33147
+ }
33148
+ } catch (error) {
33149
+ debugger;
33150
+ console.error(error);
33151
+ }
33152
+
33153
+ if (new_key === 'xu-exp' || nodeP.attributes['xu-exp:' + new_key] || glb.run_xu_before.includes(new_key) || glb.run_xu_after.includes(new_key)) {
33154
+ continue;
33155
+ }
33156
+
33157
+ if (new_key === 'xu-on') {
33158
+ let ret = await func.UI.screen.execute_xu_functions(
33159
+ SESSION_ID,
33160
+ is_skeleton,
33161
+ $root_container,
33162
+ nodeP,
33163
+ $container,
33164
+ paramsP,
33165
+ parent_infoP,
33166
+ jobNoP,
33167
+ keyP,
33168
+ parent_nodeP,
33169
+ 'xu-on',
33170
+ $elm,
33171
+ {
33172
+ key: key,
33173
+ // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
33174
+ value: await get_attr_value(key),
33175
+ },
33176
+ is_init,
33177
+ refreshed_ds,
33178
+ );
33179
+ _ret = _.assignIn(_ret, ret);
33180
+ continue;
33181
+ }
33182
+
33183
+ let ret = await func.UI.screen.execute_xu_functions(
33184
+ SESSION_ID,
33185
+ is_skeleton,
33186
+ $root_container,
33187
+ nodeP,
33188
+ $container,
33189
+ paramsP,
33190
+ parent_infoP,
33191
+ jobNoP,
33192
+ keyP,
33193
+ parent_nodeP,
33194
+ new_key,
33195
+ $elm,
33196
+ {
33197
+ key: key,
33198
+ // value: (await get_xuExp(new_key)) || func.UI.screen.fix_val_defaults(key, val),
33199
+ value: await get_attr_value(key),
33200
+ },
33201
+ is_init,
33202
+ refreshed_ds,
33203
+ );
33204
+
33205
+ _ret = _.assignIn(_ret, ret);
33206
+ }
33207
+
33208
+ // EXP for
33209
+
33210
+ for await (const [key, val] of Object.entries(nodeP.attributes)) {
33211
+ if (_ret.abort || $container?.data()?.xuData?.pending_to_delete) break;
33212
+
33213
+ const attr = key.split('xu-exp:')[1];
33214
+
33215
+ if (!attr) {
33216
+ continue;
33217
+ }
33218
+
33219
+ if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
33220
+
33221
+ if (done_exp.includes(key)) {
33222
+ continue;
33223
+ }
33224
+ let ret = await func.UI.screen.execute_xu_functions(
33225
+ SESSION_ID,
33226
+ is_skeleton,
33227
+ $root_container,
33228
+ nodeP,
33229
+ $container,
33230
+ paramsP,
33231
+ parent_infoP,
33232
+ jobNoP,
33233
+ keyP,
33234
+ parent_nodeP,
33235
+ 'xu-exp',
33236
+ $elm,
33237
+ {
33238
+ key: attr,
33239
+ value: val,
33240
+ },
33241
+ true,
33242
+ refreshed_ds,
33243
+ );
33244
+ _ret = _.assignIn(_ret, ret);
33245
+ }
33246
+
33247
+ // AFTER
33248
+
33249
+ for await (const [key, attr] of Object.entries(glb.run_xu_after)) {
33250
+ if ($container?.data()?.xuData?.pending_to_delete) break;
33251
+
33252
+ if (glb.html5_events_handler.includes(attr) || execute_attributes.includes(attr)) continue;
33253
+
33254
+ if (!nodeP.attributes || !nodeP.attributes[attr] & !nodeP.attributes[`xu-exp:${attr}`]) continue;
33255
+
33256
+ let ret = await func.UI.screen.execute_xu_functions(
33257
+ SESSION_ID,
33258
+ is_skeleton,
33259
+ $root_container,
33260
+ nodeP,
33261
+ $container,
33262
+ paramsP,
33263
+ parent_infoP,
33264
+ jobNoP,
33265
+ keyP,
33266
+ parent_nodeP,
33267
+ attr,
33268
+ $elm,
33269
+ {
33270
+ key: attr,
33271
+ // value: (await get_xuExp(attr)) || func.UI.screen.fix_val_defaults(attr, nodeP.attributes[attr]),
33272
+ value: await get_attr_value(attr),
33273
+ },
33274
+ is_init,
33275
+ refreshed_ds,
33276
+ );
33277
+ _ret = _.assignIn(_ret, ret);
33278
+ }
33279
+
33280
+ // REGISTER EVENTS ATTRIBUTES
33281
+
33282
+ for await (const [key, val] of Object.entries(nodeP.attributes)) {
33283
+ if ($container?.data()?.xuData?.pending_to_delete) break;
33284
+ if (!glb.html5_events_handler.includes(key)) break;
33285
+ // $elm.attr(key, await get_xuExp(key)) || val;
33286
+ $elm.attr(key, await get_xuExp(key)) || val;
33287
+ }
33288
+
33289
+ return _ret;
33290
+ };
33291
+
33292
+ func.UI.screen.panel_post_render_handler = async function (
33293
+ SESSION_ID,
33294
+ $container, // the parent program container
33295
+ $wrapper, // the wrapper element contains the rendered panel elements e.g: xu-single-view
33296
+ nodeP, // the xu-panel node
33297
+ $panel_div, // the panel div
33298
+ jobNoP,
33299
+ ) {
33300
+ const _container_ds = SESSION_OBJ[SESSION_ID].DS_GLB[$container.data().xuData.paramsP.dsSessionP];
33301
+ const _ds = SESSION_OBJ[SESSION_ID].DS_GLB[$wrapper.data().xuData.paramsP.dsSessionP];
33302
+ const find_old_panels_elements = function () {
33303
+ return func.UI.utils.find_in_element_data('xuPanelData', $container.parent(), 'xu-ui-id', $container.data()?.xuPanelData?.xu_panel_xu_ui_id);
33304
+ };
33305
+ var $old_panel_div = find_old_panels_elements();
33306
+ const set_xuPanelData_to_the_new_rendered_items = () => {
33307
+ $container.data().xuPanelWrapper = { isWrapper: true, panelXuAttributes: _.clone($wrapper.data().xuAttributes), panelDivData: _.clone($wrapper.data()) };
33308
+ $container.attr('xu-panel-wrapper-id', $wrapper.attr('xu-ui-id'));
33309
+ $.each($wrapper.children(), function (key, val) {
33310
+ if (!$(val).data().xuPanelData) {
33311
+ $(val).data().xuPanelData = {};
33312
+ }
33313
+ $(val).data().xuPanelData.parent_element_ui_id = $old_panel_div?.length ? $container.parent().data().xuData.ui_id : $container.data().xuData.ui_id;
33314
+
33315
+ $(val).data().xuPanelData.xu_panel_xu_ui_id = (nodeP.xu_tree_id || nodeP.id) + '-' + _container_ds?.currentRecordId;
33316
+ $(val).data().xuPanelData.node = nodeP;
33317
+ $(val).data().xuPanelData.$panel_div = $panel_div.clone(true);
33318
+ });
33319
+ };
33320
+ set_xuPanelData_to_the_new_rendered_items();
33321
+
33322
+ if ($old_panel_div?.length) {
33323
+ $($old_panel_div[0]).after($wrapper.children());
33324
+ } else {
33325
+ $.each($wrapper.children(), function (key, child) {
33326
+ $.each($container.children(), function (key, elm) {
33327
+ if ($(elm)?.data()?.xuData && $(elm)?.data()?.xuData?.elem_key === $(child)?.data()?.xuData?.elem_key) {
33328
+ $(elm).remove();
33329
+ }
33330
+ });
33331
+ $container.append($(child));
33332
+ });
33333
+ }
33334
+
33335
+ if (!$wrapper.data()?.xuData?.dsSession) return;
33336
+
33337
+ if ($old_panel_div?.length) {
33338
+ $container.parent().data().xuData.paramsP.dsSessionP = _ds.parentDataSourceNo; // set the new ds when panel replaced
33339
+ } else {
33340
+ $container.data().xuData.paramsP.dsSessionP = _ds.parentDataSourceNo; // set the new ds when panel replaced
33341
+ }
33342
+
33343
+ if ($old_panel_div?.length) {
33344
+ $old_panel_div.remove();
33345
+ }
33346
+ return jobNoP;
33347
+ };
33348
+
33349
+ const generate_xu_ui_id = async function (SESSION_ID, nodeP, $container, paramsP, keyP) {
33350
+ const _paramsP = _.cloneDeep(paramsP);
33351
+ var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_paramsP.dsSessionP];
33352
+
33353
+ const currentRecordId = $container?.data?.()?.xuData?.recordid || (_ds ? _ds.currentRecordId : '');
33354
+ const key_path = `${$container?.data()?.xuData?.key_path || '0'}-${keyP || '0'}`;
33355
+ const elem_key = `${nodeP.xu_tree_id || nodeP.id}-${key_path}-${currentRecordId}`;
33356
+ let ui_id = `${nodeP.id}-${elem_key}-${_paramsP?.dsSessionP?.toString() || ''}`; //nodeP.xu_tree_id ||
33357
+
33358
+ const new_ui_id = await func.common.sha256(ui_id);
33359
+ return new_ui_id;
33360
+ };
33361
+
33362
+ func.UI.screen.create_container = async function (SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, classP, elem_propP, div_typeP, $appendToP, attr_str, is_placeholder) {
33363
+ const _paramsP = _.cloneDeep(paramsP);
33364
+ var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[_paramsP.dsSessionP];
33365
+ var $appendTo = $container;
33366
+ if ($appendToP) $appendTo = $appendToP;
33367
+ if (!$appendTo || !$appendTo.length) return null; // screen closed or not exist abort build
33368
+ var div = 'div';
33369
+ if (div_typeP) div = div_typeP;
33370
+ var items = [];
33371
+ if (nodeP.children)
33372
+ items = nodeP.children.map(function (val) {
33373
+ return val.xu_tree_id || val.id;
33374
+ });
33375
+ var currentRecordId = $container?.data?.()?.xuData?.recordid || (_ds ? _ds.currentRecordId : '');
33376
+ // var xu_id = (glb.screen_num++).toString();
33377
+ // xu_id = xu_id += '_' + currentRecordId;
33378
+
33379
+ try {
33380
+ const key_path = `${$container?.data()?.xuData?.key_path || '0'}-${keyP || '0'}`;
33381
+ const elem_key = `${nodeP.xu_tree_id || nodeP.id}-${key_path}-${currentRecordId}`;
33382
+ // let ui_id = `${nodeP.id}-${elem_key}-${_paramsP?.dsSessionP?.toString() || ''}`; //nodeP.xu_tree_id ||
33383
+
33384
+ /////////////////////////////////
33385
+
33386
+ var $div;
33387
+
33388
+ if (div === 'svg') {
33389
+ const draw_svg = function (element) {
33390
+ const get_tag_str = function (element, prop, val) {
33391
+ let class_str = '';
33392
+ let attr_str = '';
33393
+ for (const [key, val] of Object.entries(prop)) {
33394
+ if (key.substr(0, 2) !== 'xu') {
33395
+ attr_str += ` ${key}="${val}" `;
33396
+ }
33397
+ }
33398
+ if (element === 'svg') {
33399
+ return `<${element} ${attr_str} > `;
33400
+ }
33401
+ let ret = '';
33402
+ if (val?.children?.length) {
33403
+ ret = iterate_svg(val);
33404
+ }
33405
+
33406
+ return `<${element} ${class_str} ${attr_str} > ${ret} </${element}>`;
33407
+ };
33408
+ let svg_str = get_tag_str(element, prop);
33409
+ let inner_str = '';
33410
+ const iterate_svg = function (node) {
33411
+ let ret = '';
33412
+ if (node.children) {
33413
+ for (let val of node.children) {
33414
+ let prop = val.attributes;
33415
+ ret += get_tag_str(val.tagName, prop, val);
33416
+ }
33417
+ }
33418
+ return ret;
33419
+ };
33420
+ inner_str = iterate_svg(nodeP);
33421
+
33422
+ $div = $(svg_str + inner_str + '</svg>').appendTo($appendTo);
33423
+ };
33424
+
33425
+ draw_svg(div_typeP);
33426
+ } else {
33427
+ $div = $(`<${div} ${attr_str ? attr_str : ''}>`);
33428
+ }
33429
+
33430
+ // // Returns a 32-bit unsigned integer hash of a string (FNV-1a)
33431
+ // function hash32(str) {
33432
+ // let h = 0x811c9dc5; // FNV offset basis
33433
+ // for (let i = 0; i < str.length; i++) {
33434
+ // h ^= str.charCodeAt(i);
33435
+ // // multiply by FNV prime (2^24 + 2^8 + 0x93) with 32-bit overflow
33436
+ // h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
33437
+ // }
33438
+ // // Convert to unsigned 32-bit
33439
+ // return h >>> 0;
33440
+ // }
33441
+
33442
+ // function hash32hex(str) {
33443
+ // return (hash32(str) >>> 0).toString(16).padStart(8, '0');
33444
+ // }
33445
+
33446
+ // const new_ui_id = hash32hex(ui_id);
33447
+ // const new_ui_id = await func.common.sha256(ui_id);
33448
+ const new_ui_id = await generate_xu_ui_id(SESSION_ID, nodeP, $container, paramsP, keyP);
33449
+
33450
+ $div
33451
+ .attr('xu-ui-id', new_ui_id)
33452
+ // .attr('xu-node-id', nodeP.id)
33453
+ .data({
33454
+ xuData: {
33455
+ prog_id: _paramsP.prog_id,
33456
+ nodeid: nodeP.id,
33457
+ ui_type: nodeP.tagName,
33458
+ // xu_id,
33459
+ recordid: currentRecordId,
33460
+ paramsP: _paramsP,
33461
+ key: keyP,
33462
+ key_path, //:($container?.data()?.xuData?.key || "0") + "-" + (keyP || "0"),
33463
+ screenId: _paramsP.screenId,
33464
+ parent_container: $container?.attr('id'),
33465
+ elem_key,
33466
+ properties: prop,
33467
+ node: nodeP,
33468
+ node_org: _.cloneDeep(nodeP),
33469
+ is_panelP: _paramsP.is_panelP,
33470
+ ui_id: new_ui_id,
33471
+ elem_prop: elem_propP,
33472
+ debug_info: {
33473
+ id: nodeP.id,
33474
+ parent_id: $container?.data()?.xuData?.ui_id,
33475
+ items: items,
33476
+ },
33477
+ parent_node: parent_nodeP,
33478
+ currentRecordId: currentRecordId,
33479
+ $root_container: $root_container,
33480
+ parent_element_ui_id: $container?.data()?.xuData?.ui_id,
33481
+ },
33482
+ xuAttributes: {},
33483
+ });
33484
+ if (is_placeholder) {
33485
+ $div.addClass('display_none');
33486
+ }
33487
+
33488
+ if (div_typeP !== 'svg') {
33489
+ $div.appendTo($appendTo);
33490
+ }
33491
+ } catch (e) {
33492
+ console.error(e);
33493
+ }
33494
+
33495
+ if (parent_infoP?.iterate_info) {
33496
+ $div.data().xuData.iterate_info = parent_infoP.iterate_info;
33497
+ }
33498
+
33499
+ if (classP) $div.addClass(classP);
33500
+
33501
+ return $div;
33502
+ };
33503
+ func.UI.screen.execute_screen_ready_events = async function (SESSION_ID, paramsP, sourceP, $div, jobNoP, $div_objP) {
33504
+ var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
33505
+ if (!_ds) return;
33506
+ var viewEventExec_arr = [];
33507
+ const execute_view_events = async function (sourceP) {
33508
+ for await (const val of viewEventExec_arr) {
33509
+ cond = val.eventInfo.data.enabled;
33510
+ if (val.expression) {
33511
+ expCond = await func.expression.get(SESSION_ID, val.expression, paramsP.dsSessionP, 'condition', paramsP.rowIdP); // execute expression
33512
+ cond = expCond.result;
33513
+ }
33514
+ if (cond) {
33515
+ await func.events.execute(
33516
+ SESSION_ID,
33517
+ null,
33518
+ val.eventId,
33519
+ val.triggerId,
33520
+ val.eventInfo.data.action,
33521
+ val.eventInfo.data.name,
33522
+ null,
33523
+ null,
33524
+ null,
33525
+ null,
33526
+ val.eventInfo.data.action, //val.eventInfo[4]
33527
+ null,
33528
+ paramsP.dsSessionP,
33529
+ val.eventId,
33530
+ sourceP + ' event',
33531
+ true,
33532
+ null,
33533
+ null,
33534
+ paramsP.dsSessionP,
33535
+ null,
33536
+ null,
33537
+ val.eventInfo, // val.eventInfo[8],
33538
+ null,
33539
+ null,
33540
+ _ds.prog_id,
33541
+ _ds.nodeId,
33542
+ _ds.parentDataSourceNo,
33543
+ $div,
33544
+ );
33545
+
33546
+ // update changed values to screen added 18/09/13
33547
+ var fields_to_refresh = [];
33548
+ try {
33549
+ var current_record_id = _ds.currentRecordId;
33550
+ } catch (e) {
33551
+ console.error(e);
33552
+ }
33553
+
33554
+ if (_ds?.data_feed?.form_fields_changed?.[current_record_id]) {
33555
+ $.each(_ds.data_feed.form_fields_changed[current_record_id], function (key, val) {
33556
+ fields_to_refresh.push(key);
33557
+ });
33558
+
33559
+ var containerId = _ds.containerId;
33560
+ var $container = $('#' + containerId);
33561
+ if ($container?.data()?.xuData?.is_mobile_modal || $container?.data()?.xuData?.params?.is_mobile_page) {
33562
+ await func.UI.screen.refresh_container(SESSION_ID, 'init', fields_to_refresh, $container, paramsP.dsSessionP, null);
33563
+ } else {
33564
+ $container.trigger(containerId + '.refresh', ['init', fields_to_refresh]);
33565
+ }
33566
+
33567
+ if ($div_objP) {
33568
+ await func.UI.screen.refresh_container(SESSION_ID, 'init', fields_to_refresh, $div_objP, paramsP.dsSessionP, null);
33569
+ }
33570
+ }
33571
+ }
33572
+ continue;
33573
+ }
33574
+ };
33575
+ const get_view_events_count = async function (typeP) {
33576
+ const _prog = await func.utils.VIEWS_OBJ.get(SESSION_ID, _ds.prog_id);
33577
+ viewEventExec_arr = [];
33578
+
33579
+ if (!_prog.progEvents || _.isEmpty(_prog.progEvents)) {
33580
+ return 0;
33581
+ }
33582
+ for await (const event_obj of _prog.progEvents) {
33583
+ if (event_obj.data.type !== typeP) continue;
33584
+
33585
+ if (_.isEmpty(event_obj.workflow)) continue;
33586
+
33587
+ if (event_obj.data.condition) {
33588
+ let res = await func.expression.get(SESSION_ID, event_obj.data.condition, paramsP.dsSessionP, 'condition', paramsP.rowIdP, null, null, null, null, event_obj);
33589
+ if (!res.result) {
33590
+ continue;
33591
+ }
33592
+ }
33593
+
33594
+ for await (const trigger_obj of event_obj.workflow) {
33595
+ var expression = undefined;
33596
+ var cond = undefined;
33597
+ if (!trigger_obj.data.enabled) {
33598
+ continue;
33599
+ }
33600
+ cond = true;
33601
+ if (trigger_obj.props.condition) expression = trigger_obj.props.condition;
33602
+ var expCond = {};
33603
+ if (expression) {
33604
+ expCond = await func.expression.get(SESSION_ID, expression, paramsP.dsSessionP, 'condition', paramsP.rowIdP, trigger_obj.data.type); // execute expression
33605
+ cond = expCond.result;
33606
+ expCond.conditional = true;
33607
+ }
33608
+
33609
+ if (!trigger_obj.data.action) {
33610
+ func.utils.debug_report(SESSION_ID, 'get_view_events_count', `Error initiating ${typeP} prog: ${_ds.viewSourceDesc} reason: missing action`, 'E');
33611
+ break;
33612
+ }
33613
+ if (!glb.REFERENCE_LESS_FUNCTIONS.includes(trigger_obj.data.action) && !trigger_obj.data.name?.prog) {
33614
+ func.utils.debug_report(SESSION_ID, 'get_view_events_count', `Error initiating ${typeP} prog: ${_ds.viewSourceDesc} reason: missing reference`, 'E');
33615
+ break;
33616
+ }
33617
+
33618
+ viewEventExec_arr.push({
33619
+ eventInfo: trigger_obj,
33620
+ eventId: event_obj.id,
33621
+ triggerId: trigger_obj.id,
33622
+ expression: expression,
33623
+ });
33624
+ }
33625
+ }
33626
+ return viewEventExec_arr.length;
33627
+ };
33628
+ try {
33629
+ let count = await get_view_events_count('screen_ready');
33630
+
33631
+ if (!count) return;
33632
+ return await execute_view_events(sourceP);
33633
+ } catch (error) {
33634
+ debugger;
33635
+ }
33636
+ };
33637
+ func.UI.screen.screen_loading_done = async function (SESSION_ID, paramsP, $div, jobNoP) {
33638
+ // console.log($div.attr('xu-ui-id'));
33639
+
33640
+ // await
33641
+ let retries = 0;
33642
+ let interval = setInterval(() => {
33643
+ if (!$(SESSION_OBJ[SESSION_ID].root_element).find(`[xu-ui-id=${$div.attr('xu-ui-id')}]`).length && !$(SESSION_OBJ[SESSION_ID].root_element).find(`[xu-panel-wrapper-id=${$div.attr('xu-ui-id')}]`).length && !$div.attr('xu-ui-id') && $div.attr('xu-ui-id')) {
33644
+ retries++;
33645
+ if (retries > 100) {
33646
+ console.warn('deadlock detected for screen ready');
33647
+ } else {
33648
+ return $div;
33649
+ }
33650
+ }
33651
+
33652
+ clearInterval(interval);
33653
+
33654
+ func.UI.screen.execute_screen_ready_events(SESSION_ID, paramsP, paramsP.screenInfo.properties?.renderType, $div, jobNoP);
33655
+ var _session = SESSION_OBJ[SESSION_ID];
33656
+ func.events.delete_job(SESSION_ID, jobNoP);
33657
+ func.UI.utils.screen_blocker(false, paramsP.prog_id + (paramsP.sourceScreenP ? '_' + paramsP.sourceScreenP : ''));
33658
+ if (_session.prog_id === paramsP.prog_id) {
33659
+ _session.system_ready = true;
33660
+ if (_session.engine_mode === 'live_preview' && STUDIO_PEER_CONN_SEND_METHOD) {
33661
+ STUDIO_PEER_CONN_SEND_METHOD({
33662
+ service: 'system_ready',
33663
+ data: {},
33664
+ id: STUDIO_PEER.id,
33665
+ source: 'runtime',
33666
+ session_id: SESSION_ID,
33667
+ app_id: _session.app_id,
33668
+ gtp_token: _session.gtp_token,
33669
+ app_token: _session.app_token,
33670
+ });
33671
+ // }
33672
+ }
33673
+ }
33674
+ }, 100);
33675
+
33676
+ return $div;
33677
+ };
33678
+
33679
+ func.UI.screen.render_ui_tree = async function (SESSION_ID, $container, nodeP, parent_infoP, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, $root_container) {
33680
+ if (!is_skeleton) {
33681
+ var _session = SESSION_OBJ[SESSION_ID];
33682
+ var _ds = _session.DS_GLB[paramsP.dsSessionP];
33683
+ }
33684
+ var prop;
33685
+ try {
33686
+ prop = nodeP.attributes;
33687
+ } catch (error) {
33688
+ // debugger;
33689
+ }
33690
+
33691
+ ///////////
33692
+ var is_mobile = glb.MOBILE_ARR.includes(paramsP.screenInfo.properties?.menuType) ? true : false;
33693
+
33694
+ const get_element_info = function () {
33695
+ var ret = {};
33696
+ let currentRecordId = _ds?.currentRecordId || '';
33697
+
33698
+ let $div = func.UI.utils.find_in_element_data('xuData', $container.parent(), 'nodeid', nodeP.id);
33699
+
33700
+ $.each($div, function (key, val) {
33701
+ if ($(val)?.data().xuData?.recordid === currentRecordId && $(val)?.data().xuData?.key === keyP && $(val)?.prop('tagName') !== 'XURENDER') {
33702
+ ret = {
33703
+ div: $div,
33704
+ };
33705
+ }
33706
+ });
33707
+
33708
+ return ret;
33709
+ };
33710
+
33711
+ const init = async function () {
33712
+ var ret = true;
33713
+ if (!nodeP) ret = false;
33714
+ return ret;
33715
+ };
33716
+ const debug = function (is_errorP, error_descP) {
33717
+ func.utils.debug.log(SESSION_ID, paramsP.prog_id + '_' + nodeP.id_org + '_ui_prop', {
33718
+ module: 'gui',
33719
+ action: 'init',
33720
+ prop: nodeP.id,
33721
+ details: error_descP,
33722
+ result: null,
33723
+ error: is_errorP,
33724
+ source: _ds?.tree_obj?.menuName || '',
33725
+ fields: null,
33726
+ type: null,
33727
+ prog_id: paramsP.prog_id,
33728
+ dsSession: null,
33729
+ });
33730
+ };
33731
+
33732
+ const open_modal = async function ($div) {
33733
+ const modal_id = 'app_modal-' + paramsP.dsSessionP.toString();
33734
+ var xu_modal_controller = document.querySelector('xu-modal-controller');
33735
+ if (!xu_modal_controller) {
33736
+ func.UI.component.create_app_modal_component(SESSION_ID, modal_id);
33737
+ xu_modal_controller = document.querySelector('xu-modal-controller');
33738
+ }
33739
+
33740
+ var controller_params = $(xu_modal_controller).data('xuControllerParams');
33741
+
33742
+ if (!controller_params) {
33743
+ controller_params = {};
33744
+ }
33745
+
33746
+ var params = {
33747
+ menuTitle: paramsP.screenInfo.properties?.menuTitle,
33748
+ screenId: paramsP.screenId,
33749
+ $dialogDiv: $div.children(),
33750
+ $container: $container,
33751
+ dsSession: paramsP.dsSessionP,
33752
+ };
33753
+
33754
+ controller_params[modal_id] = params;
33755
+
33756
+ $(xu_modal_controller).data('xuControllerParams', controller_params);
33757
+ const modalController = await new UI_FRAMEWORK_PLUGIN.modal();
33758
+
33759
+ if (!APP_MODAL_OBJ[modal_id]) {
33760
+ const modal = await modalController.create(SESSION_ID, modal_id, paramsP.screenInfo, close_modal);
33761
+ APP_MODAL_OBJ[modal_id] = modal;
33762
+ } else {
33763
+ $(modal_id).empty();
33764
+ }
33765
+ await modalController.init(SESSION_ID, modal_id);
33766
+
33767
+ return $div;
33768
+ };
33769
+
33770
+ const close_modal = async function (modal_id) {
33771
+ delete APP_MODAL_OBJ[modal_id];
33772
+ const xu_modal_controller = document.querySelector('xu-modal-controller');
33773
+ var params = $(xu_modal_controller).data().xuControllerParams[modal_id];
33774
+ if (params && params.$container) {
33775
+ await func.UI.screen.validate_exit_events(SESSION_ID, params.$container.data().xuData.paramsP, null);
33776
+ func.datasource.clean_all(SESSION_ID, params.dsSession);
33777
+ }
33778
+ };
33779
+
33780
+ const close_all_modals = function () {
33781
+ $.each(APP_MODAL_OBJ, function (key, val) {
33782
+ if (val) {
33783
+ // close_modal(key);
33784
+ UI_FRAMEWORK_PLUGIN.modal.close(key);
33785
+ }
33786
+ });
33787
+ };
33788
+
33789
+ const open_popover = async function ($div) {
33790
+ const xu_popover_controller = func.UI.component.create_app_popover_component(SESSION_ID);
33791
+
33792
+ $(xu_popover_controller).data('xuControllerParams', {
33793
+ menuTitle: paramsP.screenInfo.properties?.menuTitle,
33794
+ screenId: paramsP.screenId,
33795
+ $dialogDiv: $div.children(),
33796
+ $container: $container,
33797
+ });
33798
+ const popover = new UI_FRAMEWORK_PLUGIN.popover(
33799
+ SESSION_ID,
33800
+ // ELEMENT_CLICK_EVENT,
33801
+ // props
33802
+ );
33803
+ await popover.open(SESSION_ID);
33804
+ CURRENT_APP_POPOVER = popover;
33805
+
33806
+ return;
33807
+ popoverController
33808
+ .create({
33809
+ component: 'xu-popover-content-' + SESSION_ID,
33810
+ event: ELEMENT_CLICK_EVENT,
33811
+ translucent: true,
33812
+ })
33813
+ .then((modal) => {
33814
+ modal.present().then(() => {
33815
+ CURRENT_APP_POPOVER = modal;
33816
+
33817
+ if (callbackP) callbackP($div);
33818
+ });
33819
+ });
33820
+ };
33821
+ const iterate_child = async function ($divP, nodeP, parent_infoP, $root_container, before_record_function) {
33822
+ if (!is_mobile && nodeP.busy) return;
33823
+ nodeP.busy = true;
33824
+ const done = async function ($divP) {
33825
+ setTimeout(function () {
33826
+ nodeP.busy = false;
33827
+ }, 1000);
33828
+
33829
+ return $divP;
33830
+ };
33831
+ if (!nodeP || !nodeP.children) {
33832
+ return await done($divP);
33833
+ }
33834
+
33835
+ if (before_record_function) {
33836
+ await before_record_function();
33837
+ }
33838
+ if (nodeP?.children?.length) {
33839
+ let node_promises = [];
33840
+ for (const [key, val] of Object.entries(nodeP.children)) {
33841
+ node_promises.push(
33842
+ new Promise(async (resolve, reject) => {
33843
+ const ret = await func.UI.screen.render_ui_tree(SESSION_ID, $divP, nodeP.children[key], parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, nodeP, null, $root_container);
33844
+
33845
+ resolve();
33846
+ }),
33847
+ );
33848
+ }
33849
+ await Promise.all(node_promises);
33850
+ }
33851
+ return await done($divP);
33852
+ };
33853
+
33854
+ // const iterate_child = async function ($divP, nodeP, parent_infoP, $root_container, before_record_function) {
33855
+ // if (!is_mobile && nodeP.busy) return;
33856
+ // nodeP.busy = true;
33857
+ // const done = async function ($divP) {
33858
+ // setTimeout(function () {
33859
+ // nodeP.busy = false;
33860
+ // }, 1000);
33861
+
33862
+ // return $divP;
33863
+ // };
33864
+ // if (!nodeP || !nodeP.children) {
33865
+ // return await done($divP);
33866
+ // }
33867
+
33868
+ // if (before_record_function) {
33869
+ // await before_record_function();
33870
+ // }
33871
+ // if (nodeP?.children?.length) {
33872
+ // for await (const [key, val] of Object.entries(nodeP.children)) {
33873
+ // const ret = await func.UI.screen.render_ui_tree(SESSION_ID, $divP, nodeP.children[key], parent_infoP, paramsP, jobNoP, is_skeleton, Number(key), null, nodeP, null, $root_container);
33874
+ // }
33875
+ // }
33876
+ // return await done($divP);
33877
+ // };
33878
+
33879
+ const _$ = function ($elm) {
33880
+ try {
33881
+ const id = $elm.attr('xu-ui-id');
33882
+ if (!id || !glb.DEBUG_MODE) return $elm;
33883
+ const $el = $(`[xu-ui-id="${id}"]`);
33884
+
33885
+ if ($el.length > 1) {
33886
+ console.warn('Multiple elements for xu-ui-id: ' + id, $el);
33887
+ }
33888
+
33889
+ return $($el[0]);
33890
+ } catch (e) {
33891
+ console.error(e);
33892
+ }
33893
+ };
33894
+
33895
+ const hover_in = function ($div, e) {
33896
+ if (is_skeleton || (e && (EXP_BUSY || UI_WORKER_OBJ.jobs.length))) return;
33897
+ CLIENT_ACTIVITY_TS = Date.now();
33898
+ if (_$($container)?.data()?.xuData?.debug_info) _$($container).data().xuData.debug_info.hover_item = $div.attr('xu-ui-id');
33899
+ if (!_ds) return;
33900
+ ///////// SET Attributes///////////
33901
+ let attributes = {};
33902
+ $.each($div[0].attributes, function (index, attr) {
33903
+ attributes[attr.name] = attr.value;
33904
+ });
33905
+
33906
+ _session.DS_GLB[0].data_system.SYS_OBJ_WIN_ELEMENT_HOVERED_ATTRIBUTES = attributes;
33907
+ //////////////////////////////////
33908
+ if (!$div.data()?.xuData) return;
33909
+ const _iterate_info = $div.data().xuData.iterate_info;
33910
+ if (_iterate_info) {
33911
+ if (_iterate_info.is_key_dynamic_field) {
33912
+ _ds.dynamic_fields[_iterate_info.iterator_key].value = _iterate_info._key;
33913
+ } else {
33914
+ try {
33915
+ const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
33916
+ _ds.data_feed.rows[row_idx][_iterate_info.iterator_key] = _iterate_info._key;
33917
+ } catch (err) {
33918
+ console.error(err);
33919
+ }
33920
+ }
33921
+
33922
+ if (_iterate_info.is_val_dynamic_field) {
33923
+ _ds.dynamic_fields[_iterate_info.iterator_val].value = _iterate_info._val;
33924
+ } else {
33925
+ try {
33926
+ const row_idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
33927
+ _ds.data_feed.rows[row_idx][_iterate_info.iterator_val] = _iterate_info._val;
33928
+ } catch (err) {
33929
+ console.error(err);
33930
+ }
33931
+ }
33932
+ }
33933
+
33934
+ if ($div && _$($div) && _ds && paramsP.renderType === 'grid') {
33935
+ func.UI.worker.add_to_queue(SESSION_ID, 'gui event', 'update_datasource', { currentRecordId: _$($div).data().xuData.currentRecordId }, null, null, paramsP.dsSessionP);
33936
+ }
33937
+
33938
+ const set_value = function (field_id, value) {
33939
+ var currentRecordId = _$($div).data().xuData.currentRecordId;
33940
+
33941
+ func.UI.worker.add_to_queue(
33942
+ SESSION_ID,
33943
+ 'gui event',
33944
+ 'update_datasource',
33945
+ {
33946
+ currentRecordId,
33947
+ field_id,
33948
+ field_value: value,
33949
+ },
33950
+ null,
33951
+ null,
33952
+ paramsP.dsSessionP,
33953
+ );
33954
+ };
33955
+
33956
+ if ($div?.data()?.iterate_info) {
33957
+ var data = $div.data().xuData.iterate_info;
33958
+ if (data.iterator_key) {
33959
+ set_value(data.iterator_key, data._key);
33960
+ }
33961
+ if (data.iterator_val) {
33962
+ set_value(data.iterator_val, data._val);
33963
+ }
33964
+ }
33965
+ };
33966
+ const hover_out = function () {
33967
+ if (is_skeleton) return;
33968
+
33969
+ CLIENT_ACTIVITY_TS = Date.now();
33970
+ if (_$($container)?.data()?.xuData?.debug_info) {
33971
+ _$($container).data().xuData.debug_info.hover_item = null;
33972
+ }
33973
+ if (_ds?.data_system) {
33974
+ SESSION_OBJ[SESSION_ID].DS_GLB[0].data_system.SYS_OBJ_WIN_ELEMENT_HOVERED_ATTRIBUTES = {};
33975
+ }
33976
+ };
33977
+ const render_screen_type = async function ($div) {
33978
+ const set_call_screen_properties_values = async function (ui_framework) {
33979
+ params.properties = {};
33980
+ const get_values = async function (property) {
33981
+ var property_value = paramsP?.screenInfo?.properties?.[property] || paramsP?.screenInfo?.properties?.frameworkProperties?.[property];
33982
+ if (paramsP?.call_screen_propertiesP) {
33983
+ if (paramsP.call_screen_propertiesP?.[property]) {
33984
+ property_value = paramsP.call_screen_propertiesP[property];
33985
+ }
33986
+ if (paramsP.call_screen_propertiesP[`xu-exp:${property}`]) {
33987
+ property_value = (await func.expression.get(SESSION_ID, paramsP.call_screen_propertiesP[`xu-exp:${property}`], paramsP.dsSessionP, property)).result;
33988
+ }
33989
+ }
33990
+ return property_value;
33991
+ };
33992
+ params.properties['name'] = await get_values('menuTitle');
33993
+ if (await ui_framework?.properties()) {
33994
+ for await (const [key, val] of Object.entries(await ui_framework.properties())) {
33995
+ params.properties[key] = await get_values(key);
33996
+ }
33997
+ }
33998
+ };
33999
+
34000
+ var $div_content = $div.children();
34001
+
34002
+ $.each($div_content, function (key, val) {
34003
+ if (!$(val)?.data()?.xuData?.parent_container) {
34004
+ return true;
34005
+ }
34006
+ $(val).data().xuData.parent_container = $div.data().xuData.parent_container;
34007
+ });
34008
+
34009
+ let $ret = $div;
34010
+ var $nav = $(SESSION_OBJ[SESSION_ID].root_element).find('xu-nav');
34011
+ var params;
34012
+ switch (paramsP.screen_type) {
34013
+ case 'modal':
34014
+ const modal_id = 'app_modal-' + paramsP.dsSessionP.toString();
34015
+ var xu_modal_controller = document.querySelector('xu-modal-controller');
34016
+ if (!xu_modal_controller) {
34017
+ func.UI.component.create_app_modal_component(SESSION_ID, modal_id);
34018
+ xu_modal_controller = document.querySelector('xu-modal-controller');
34019
+ }
34020
+
34021
+ var controller_params = $(xu_modal_controller).data('xuControllerParams');
34022
+
34023
+ if (!controller_params) {
34024
+ controller_params = {};
34025
+ }
34026
+
34027
+ params = {
34028
+ screenId: paramsP.screenId,
34029
+ $dialogDiv: $div.children(),
34030
+ $container: $container,
34031
+ dsSession: paramsP.dsSessionP,
34032
+ modal_id,
34033
+ screenInfo: paramsP.screenInfo,
34034
+ close_callback: close_modal,
34035
+ paramsP,
34036
+ };
34037
+
34038
+ controller_params[modal_id] = params;
34039
+
34040
+ $(xu_modal_controller).data('xuControllerParams', controller_params);
34041
+ const modalController = await new UI_FRAMEWORK_PLUGIN.modal();
34042
+ await set_call_screen_properties_values(modalController);
34043
+ if (!APP_MODAL_OBJ[modal_id]) {
34044
+ const modal = await modalController.create(params);
34045
+
34046
+ APP_MODAL_OBJ[modal_id] = modal;
34047
+ } else {
34048
+ $(modal_id).empty();
34049
+ }
34050
+
34051
+ await modalController.init(params);
34052
+
34053
+ break;
34054
+
34055
+ case 'popover':
34056
+ // open_popover($div);
34057
+
34058
+ const xu_popover_controller = func.UI.component.create_app_popover_component(SESSION_ID);
34059
+ params = {
34060
+ menuTitle: paramsP.screenInfo.properties?.menuTitle,
34061
+ screenId: paramsP.screenId,
34062
+ $dialogDiv: $div.children(),
34063
+ $container: $container,
34064
+ };
34065
+
34066
+ $(xu_popover_controller).data('xuControllerParams', params);
34067
+ const popover = new UI_FRAMEWORK_PLUGIN.popover(SESSION_ID);
34068
+ await set_call_screen_properties_values(popover);
34069
+ await popover.open(params);
34070
+ CURRENT_APP_POPOVER = popover;
34071
+
34072
+ func.UI.utils.screen_blocker(false, paramsP.prog_id + '_' + paramsP.sourceScreenP);
34073
+ break;
34074
+
34075
+ case 'page':
34076
+ const nav = $nav[0];
34077
+
34078
+ params = {
34079
+ div: $div_content,
34080
+ name: paramsP.screenInfo.properties?.menuTitle,
34081
+ screenId: paramsP.screenId,
34082
+ $container: $container,
34083
+ dsSession: paramsP.dsSessionP,
34084
+ SESSION_ID,
34085
+ nav,
34086
+ paramsP,
34087
+ };
34088
+
34089
+ var component_name = 'xu-page-component-' + paramsP.dsSessionP;
34090
+ if (!$(nav).data().xuData.nav_params) {
34091
+ $(nav).data().xuData.nav_params = {};
34092
+ }
34093
+
34094
+ //restore validate
34095
+ if ($(nav)?.data()?.xuData?.params?.[paramsP.dsSessionP]) {
34096
+ params.$container.data().xuData.validate_screen_ready = $(nav).data().xuData.params[paramsP.dsSessionP].$container.data().xuData.validate_screen_ready;
34097
+ }
34098
+
34099
+ if (!$(nav)?.data()?.xuData) return;
34100
+ $(nav).data().xuData.nav_params[paramsP.dsSessionP] = params;
34101
+ if (!$(component_name).length) {
34102
+ await func.UI.component.create_app_page_component(SESSION_ID, paramsP.dsSessionP);
34103
+ const page = new UI_FRAMEWORK_PLUGIN.page();
34104
+ await set_call_screen_properties_values(page);
34105
+ await page.create(params);
34106
+ await page.init(params);
34107
+ nav.push(component_name, { params });
34108
+ } else {
34109
+ debugger;
34110
+ $(component_name).empty();
34111
+
34112
+ await UI_FRAMEWORK_PLUGIN.page(SESSION_ID, paramsP.dsSessionP);
34113
+ }
34114
+ $div.data().xuData.paramsP = $container.data().xuData.paramsP;
34115
+ break;
34116
+
34117
+ case 'panel':
34118
+ $container.append($div_content);
34119
+ $ret = $container;
34120
+ break;
34121
+
34122
+ default: // set data to nav to use in the component
34123
+ if ($nav && $nav.length) {
34124
+ // refresh made
34125
+ } else {
34126
+ $nav = $('<xu-nav>'); //.attr('xu-ui-id', SESSION_ID);
34127
+ $container.append($nav);
34128
+ func.UI.component.init_xu_nav($container, $nav);
34129
+ }
34130
+
34131
+ $nav.data().xuData.$div = $div_content;
34132
+
34133
+ await $nav[0].setRoot('xu-root-component-' + SESSION_ID);
34134
+ $ret = $container;
34135
+ break;
34136
+ }
34137
+ return $ret;
34138
+ };
34139
+
34140
+ if (!(await init())) return;
34141
+ debug();
34142
+ const fx = {
34143
+ widget: async function () {
34144
+ var _session = SESSION_OBJ[SESSION_ID];
34145
+
34146
+ var exist_elm_obj = get_element_info();
34147
+ var $div = exist_elm_obj.div;
34148
+ if (!exist_elm_obj.div) {
34149
+ $div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, 'widget_wrapper', null, null, null, null);
34150
+
34151
+ //////////////////////////
34152
+
34153
+ let plugin_name = prop['xu-widget'],
34154
+ method = prop['xu-method'],
34155
+ dsP = paramsP.dsSessionP,
34156
+ propsP = prop,
34157
+ sourceP = 'widgets';
34158
+
34159
+ // const set_SYS_GLOBAL_OBJ_WIDGET_INFO = async function (docP) {
34160
+ // var obj = _.clone(docP);
34161
+ // obj.date = await func.utils.get_dateTime(
34162
+ // SESSION_ID,
34163
+ // "SYS_DATE",
34164
+ // docP.date
34165
+ // );
34166
+ // obj.time = await func.utils.get_dateTime(
34167
+ // SESSION_ID,
34168
+ // "SYS_TIME",
34169
+ // docP.date
34170
+ // );
34171
+
34172
+ // var datasource_changes = {
34173
+ // [0]: {
34174
+ // ["data_system"]: {
34175
+ // ["SYS_GLOBAL_OBJ_WIDGET_INFO"]: obj,
34176
+ // },
34177
+ // },
34178
+ // };
34179
+ // await func.datasource.update(SESSION_ID, datasource_changes);
34180
+ // };
34181
+ const call_plugin_api = async function (plugin_nameP, dataP) {
34182
+ return await func.utils.call_plugin_api(SESSION_ID, plugin_nameP, dataP);
34183
+ };
34184
+ const report_error = function (descP, warn) {
34185
+ func.utils.debug.log(SESSION_ID, _session.DS_GLB[dsP].prog_id + '_' + _session.DS_GLB[dsP].callingMenuId, {
34186
+ module: 'widgets',
34187
+ action: 'Init',
34188
+ source: sourceP,
34189
+ prop: descP,
34190
+ details: descP,
34191
+ result: null,
34192
+ error: warn ? false : true,
34193
+ fields: null,
34194
+ type: 'widgets',
34195
+ prog_id: _session.DS_GLB[dsP].prog_id,
34196
+ });
34197
+ };
34198
+ const get_fields_data = async function (fields, props) {
34199
+ const report_error = function (descP, warn) {
34200
+ func.utils.debug.log(SESSION_ID, _session.DS_GLB[dsP].prog_id + '_' + _session.DS_GLB[dsP].callingMenuId, {
34201
+ module: 'widgets',
34202
+ action: 'Init',
34203
+ source: sourceP,
34204
+ prop: descP,
34205
+ details: descP,
34206
+ result: null,
34207
+ error: warn ? false : true,
34208
+ fields: null,
34209
+ type: 'widgets',
34210
+ prog_id: _session.DS_GLB[dsP].prog_id,
34211
+ });
34212
+ };
34213
+ const get_property_value = async function (fieldIdP, val) {
34214
+ if (!val) return;
34215
+ var value = fieldIdP in props ? props[fieldIdP] : typeof val.defaultValue === 'function' ? val?.defaultValue?.() : val?.defaultValue;
34216
+ if (val.render === 'eventId') {
34217
+ value = props?.[fieldIdP]?.event;
34218
+ }
34219
+
34220
+ if (props[`xu-exp:${fieldIdP}`]) {
34221
+ value = (await func.expression.get(SESSION_ID, props[`xu-exp:${fieldIdP}`], dsP, 'widget property')).result;
34222
+ }
34223
+
34224
+ return func.common.get_cast_val(
34225
+ SESSION_ID,
34226
+ 'widgets',
34227
+ fieldIdP,
34228
+ val.type, //val.type !== "string" || val.type !== "number" ? "string" : val.type,
34229
+ value,
34230
+ null,
34231
+ );
34232
+ };
34233
+ var data_obj = {};
34234
+ var return_code = 1;
34235
+ // $.each(fields, function (key, val) {
34236
+ for await (const [key, val] of Object.entries(fields)) {
34237
+ data_obj[key] = await get_property_value(key, val);
34238
+ if (!data_obj[key] && val.mandatory) {
34239
+ return_code = -1;
34240
+ report_error(`${key} is a mandatory field.`);
34241
+ break;
34242
+ }
34243
+ // console.log(val);
34244
+ }
34245
+ for await (const key of ['xu-bind']) {
34246
+ data_obj[key] = await get_property_value(key, props[key]);
34247
+ }
34248
+
34249
+ return { code: return_code, data: data_obj };
34250
+ };
34251
+
34252
+ const load_css_style = function () {
34253
+ const get_css_path = function (resource) {
34254
+ if (_session.worker_type === 'Dev') {
34255
+ return `../../plugins/${plugin_name}/${resource}`;
34256
+ }
34257
+ return `https://${_session.domain}/plugins/${plugin_name}/${APP_OBJ[_session.app_id].app_plugins_purchased[plugin_name].manifest[resource].dist ? 'dist/' : ''}${resource}?gtp_token=${_session.gtp_token}&app_id=${_session.app_id}`;
34258
+ };
34259
+ let path = get_css_path('style.css');
34260
+ func.utils.load_css_on_demand(path);
34261
+ };
34262
+
34263
+ const _plugin = APP_OBJ[_session.app_id]?.app_plugins_purchased?.[plugin_name];
34264
+ const index = await func.utils.get_plugin_resource(SESSION_ID, plugin_name, `${_plugin.manifest['index.mjs'].dist ? 'dist/' : ''}index.mjs`);
34265
+ const methods = index.methods;
34266
+ if (methods && !methods[method]) {
34267
+ return report_error('method not found');
34268
+ }
34269
+
34270
+ const fields_ret = await get_fields_data(methods[method].fields, propsP);
34271
+ if (fields_ret.code < 0) {
34272
+ return report_error(fields_ret.data);
34273
+ }
34274
+ const fields = fields_ret.data;
34275
+
34276
+ let exclude_attributes = [];
34277
+ for await (const [key, val] of Object.entries(propsP)) {
34278
+ if (typeof fields[key] !== 'undefined' || typeof fields[`xu-exp:${key}`] !== 'undefined') {
34279
+ exclude_attributes.push(key);
34280
+ }
34281
+ }
34282
+
34283
+ let ret = await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $div, true, exclude_attributes);
34284
+
34285
+ $div.addClass('widget_wrapper'); // class get override in set_attributes_new
34286
+
34287
+ if (!APP_OBJ[_session.app_id].app_plugins_purchased[plugin_name]) {
34288
+ return report_error(`plugin ${plugin_name} not found`);
34289
+ }
34290
+
34291
+ if (APP_OBJ[_session.app_id].app_plugins_purchased[plugin_name].manifest['style.css'].exist) {
34292
+ load_css_style();
34293
+ }
34294
+
34295
+ const plugin_setup_ret = await func.utils.get_plugin_setup(SESSION_ID, plugin_name);
34296
+ if (plugin_setup_ret.code < 0) {
34297
+ return report_error(plugin_setup_ret);
34298
+ }
34299
+
34300
+ const api_utils = await func.common.get_module(SESSION_ID, 'xuda-api-library.mjs', {
34301
+ func,
34302
+ glb,
34303
+ SESSION_OBJ,
34304
+ SESSION_ID,
34305
+ APP_OBJ,
34306
+ dsSession: paramsP.dsSessionP,
34307
+ job_id: jobNoP,
34308
+ });
34309
+
34310
+ const params = {
34311
+ SESSION_ID,
34312
+ method,
34313
+ _session,
34314
+ dsP,
34315
+ sourceP,
34316
+ propsP,
34317
+ plugin_name,
34318
+ $containerP: $div,
34319
+ plugin_setup: plugin_setup_ret.data,
34320
+
34321
+ report_error,
34322
+ call_plugin_api,
34323
+ // set_SYS_GLOBAL_OBJ_WIDGET_INFO,
34324
+ api_utils,
34325
+ };
34326
+
34327
+ const fx = await func.utils.get_plugin_resource(SESSION_ID, plugin_name, `${_plugin.manifest['runtime.mjs'].dist ? 'dist/' : ''}runtime.mjs`);
34328
+
34329
+ if (_plugin?.manifest?.['runtime.mjs'].dist && _plugin?.manifest?.['runtime.mjs']?.css) {
34330
+ const plugin_runtime_css_url = await func.utils.get_plugin_npm_cdn(SESSION_ID, plugin_name, 'dist/runtime.css');
34331
+ func.utils.load_css_on_demand(plugin_runtime_css_url);
34332
+ }
34333
+
34334
+ if (!fx[method]) {
34335
+ throw `Method: ${method} does not exist`;
34336
+ }
34337
+ try {
34338
+ await fx[method](fields, params);
34339
+ } catch (err) {
34340
+ func.utils.debug_report(SESSION_ID, `${plugin_name} widget`, err.message, 'E');
34341
+ }
34342
+ }
34343
+ return $div;
34344
+ },
34345
+ [`xu-single-view`]: async function () {
34346
+ var exist_elm_obj = get_element_info();
34347
+ var $div = exist_elm_obj.div;
34348
+
34349
+ if (!exist_elm_obj.div) {
34350
+ var $wrapper = $('<div>');
34351
+ $div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, null, null, 'div', $wrapper, '');
34352
+
34353
+ if (!$div) return;
34354
+
34355
+ if (!REFRESHER_IN_PROGRESS && (paramsP.is_mobile_popover || paramsP.is_mobile_page)) {
34356
+ close_all_modals();
34357
+ }
34358
+
34359
+ $div.hover(
34360
+ function (e) {
34361
+ hover_in();
34362
+ // func.UI.screen.hover_in(SESSION_ID, null, $container, paramsP, is_skeleton);
34363
+ },
34364
+ function (e) {
34365
+ // func.UI.screen.hover_out(SESSION_ID, $container, is_skeleton, paramsP);
34366
+ hover_out();
34367
+ },
34368
+ );
34369
+ }
34370
+
34371
+ const ret = await iterate_child($div, nodeP, null, $div);
34372
+ if (_.isEmpty($container.data().xuAttributes)) {
34373
+ await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $container, true);
34374
+ }
34375
+
34376
+ $.each($div.data().xuData, function (key, val) {
34377
+ $container.data().xuData[key] = _.cloneDeep(val);
34378
+ });
34379
+ $.each($div.data().xuAttributes, function (key, val) {
34380
+ $container.data().xuAttributes[key] = _.cloneDeep(val);
34381
+ });
34382
+
34383
+ return await render_screen_type($div);
34384
+ },
34385
+ [`xu-multi-view`]: async function () {
34386
+ var $div = $container;
34387
+
34388
+ if (!$div.data().xuData.node || !$div.data().xuData.node.children) {
34389
+ $div.data().xuData.node = nodeP;
34390
+ }
34391
+
34392
+ if (!$div.data().xuData.debug_info) {
34393
+ $div.data().xuData.debug_info = {
34394
+ id: nodeP.id,
34395
+ parent_id: $container.data().xuData.ui_id,
34396
+ };
34397
+ }
34398
+
34399
+ const done = async function (continuous_idx) {
34400
+ // const do_callback = async function ($div) {
34401
+ // // if ($root_container.data().xuData.progress_bar_circle) {
34402
+ // // setTimeout(function () {
34403
+ // // $.each(
34404
+ // // $root_container.data().xuData.progress_bar_circle,
34405
+ // // function (key, val) {
34406
+ // // val.bar.set(parseFloat(val.value)); // Number from 0.0 to 1.0
34407
+ // // }
34408
+ // // );
34409
+ // // }, 2000);
34410
+ // // }
34411
+
34412
+ // if (paramsP.screenInfo.properties?.rtl) {
34413
+ // $div_content.attr('dir', 'rtl');
34414
+ // }
34415
+
34416
+ // return $div;
34417
+ // };
34418
+ await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $container, true);
34419
+
34420
+ return await render_screen_type($div);
34421
+ };
34422
+
34423
+ if (!REFRESHER_IN_PROGRESS && (paramsP.is_mobile_popover || paramsP.is_mobile_page)) {
34424
+ close_all_modals();
34425
+ }
34426
+
34427
+ const empty_result = async function () {
34428
+ // var content = prop.empty_result_content || '';
34429
+
34430
+ // var res = await func.expression.get(
34431
+ // SESSION_ID,
34432
+ // content, // prop["xu-exp:empty_result_content"],
34433
+ // paramsP.dsSessionP,
34434
+ // 'empty_result_content_EXP',
34435
+ // _ds.currentRecordId,
34436
+ // );
34437
+ // content = res.result;
34438
+
34439
+ // let empty_result_node = {
34440
+ // type: 'element',
34441
+ // id: crypto.randomUUID(),
34442
+ // content,
34443
+ // // : content || (typeof content === "undefined" && "Empty results"),
34444
+ // tagName: 'div',
34445
+ // attributes: {},
34446
+ // children: [],
34447
+ // };
34448
+
34449
+ // const ret = await func.UI.screen.render_ui_tree(SESSION_ID, $container, empty_result_node, parent_infoP, paramsP, jobNoP, null, 0, null, nodeP, null, $root_container);
34450
+ await func.events.validate(SESSION_ID, 'record_not_found', paramsP.dsSessionP);
34451
+ return await done(null);
34452
+ };
34453
+ var _ds = SESSION_OBJ[SESSION_ID].DS_GLB[paramsP.dsSessionP];
34454
+
34455
+ var continuous_idx = null;
34456
+
34457
+ if (!_ds.data_feed || _.isEmpty(_ds.data_feed.rows)) {
34458
+ return await empty_result();
34459
+ }
34460
+
34461
+ var i = 0;
34462
+ for await (const [key, val] of Object.entries(_ds.data_feed.rows)) {
34463
+ var node = JSON.parse(JSON.stringify(nodeP));
34464
+
34465
+ _ds.currentRecordId = val._ROWID;
34466
+ const ret = await iterate_child($div, node, { continuous_idx }, $root_container);
34467
+
34468
+ if (_.isEmpty($container.data().xuAttributes)) {
34469
+ await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $container, true);
34470
+ }
34471
+ }
34472
+
34473
+ return await done(continuous_idx);
34474
+ },
34475
+ [`xu-panel`]: async function () {
34476
+ const done = async function ($new_div) {
34477
+ if (!$container.data()?.xuData?.paramsP) {
34478
+ return $container;
34479
+ }
34480
+ var $div_items = $div.data().xuData.node.children;
34481
+
34482
+ await func.UI.screen.panel_post_render_handler(SESSION_ID, $container, $new_div, nodeP, $div, jobNoP);
34483
+
34484
+ // TO FIX should be timeout
34485
+ $container.data().xuData.node.children = $div_items;
34486
+
34487
+ return $container;
34488
+ };
34489
+
34490
+ var $wrapper = $('<div>');
34491
+ $div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, null, null, null, $wrapper, '');
34492
+
34493
+ let ret = await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $div.clone(true), true, undefined, refreshed_ds);
34494
+ if (ret.abort) {
34495
+ // render N
34496
+ return (ret.$new_div = $('<template>').append($div));
34497
+ }
34498
+
34499
+ let $ret_panel_div = ret.$new_div;
34500
+
34501
+ if (!$ret_panel_div?.children()?.length) {
34502
+ ////// render default children tree
34503
+ if (nodeP.children.length) {
34504
+ $ret_panel_div = await func.UI.screen.render_ui_tree(SESSION_ID, $container, nodeP.children[0], parent_infoP, paramsP, jobNoP, null, 0, null, nodeP, null, $root_container);
34505
+ }
34506
+ }
34507
+
34508
+ let ret_done = await done($ret_panel_div);
34509
+
34510
+ return ret_done;
34511
+ },
34512
+ };
34513
+
34514
+ const draw_html_element_org = async function (element) {
34515
+ const done = async function (ret = {}) {
34516
+ return $div;
34517
+ };
34518
+ if (!element || element === 'script') return await done();
34519
+ let str = '';
34520
+
34521
+ var $div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, null, null, element, null, str);
34522
+
34523
+ $div.hover(
34524
+ function (e) {
34525
+ hover_in($div, e);
34526
+ },
34527
+ function (e) {
34528
+ hover_out();
34529
+ },
34530
+ );
34531
+ if (paramsP.paramsP === 'grid' || parent_infoP?.iterate_info) {
34532
+ $div.on('click contextmenu', function (e) {
34533
+ hover_in($div, e);
34534
+ });
34535
+ }
34536
+
34537
+ // let ret = await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $container, nodeP, $div, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $div, true);
34538
+ let ret = await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $div, true);
34539
+ if (ret.abort || nodeP.tagName === 'svg' || !_.isEmpty(nodeP?.attributes?.['xu-text']) || !_.isEmpty(nodeP?.attributes?.['xu-html']) || !_.isEmpty(nodeP?.attributes?.['xu-exp:xu-text']) || !_.isEmpty(nodeP?.attributes?.['xu-exp:xu-html'])) {
34540
+ return await done(ret);
34541
+ }
34542
+ // check if iterator made to prevent children render
34543
+
34544
+ if (nodeP?.attributes?.['xu-viewport'] == 'true') {
34545
+ // const xu_viewport = async function () {
34546
+ // const data = { $div: $div.clone(true), nodeP, parent_infoP, $root_container, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, $container };
34547
+ // const container_id = $container.attr('xu-ui-id');
34548
+ // if (!UI_WORKER_OBJ.pending_for_viewport_render[container_id]) {
34549
+ // UI_WORKER_OBJ.pending_for_viewport_render[container_id] = { base_$div: $div, data: [], $container };
34550
+ // await iterate_child($div, nodeP, parent_infoP, $root_container);
34551
+ // } else {
34552
+ // $div.remove();
34553
+ // }
34554
+ // UI_WORKER_OBJ.pending_for_viewport_render[container_id].data.push(data);
34555
+
34556
+ // // if (!$div.children().length) {
34557
+ // // // render the first element to determine height
34558
+ // // await iterate_child($div, nodeP, parent_infoP, $root_container);
34559
+ // // // hover_in($div);
34560
+ // // // func.UI.worker.add_to_queue(SESSION_ID, 'gui event', 'render_viewport', data, null, null, paramsP.dsSessionP);
34561
+ // // } else {
34562
+ // // }
34563
+ // };
34564
+ const xu_viewport = function () {
34565
+ const observer_inViewport = new IntersectionObserver(
34566
+ function (entries) {
34567
+ entries.forEach((entry) => {
34568
+ if (entry.isIntersecting) {
34569
+ $(entry.target).trigger('inViewport');
34570
+
34571
+ // Optional: stop observing once triggered
34572
+ observer_inViewport.unobserve(entry.target);
34573
+ }
34574
+ });
34575
+ },
34576
+ {
34577
+ threshold: 0.1, // Trigger when 10% of element is visible
34578
+ },
34579
+ );
34580
+
34581
+ const observer_outViewport = new IntersectionObserver(
34582
+ function (entries) {
34583
+ entries.forEach((entry) => {
34584
+ if (!entry.isIntersecting) {
34585
+ // Element is OUT of viewport - trigger custom event
34586
+ $(entry.target).trigger('outViewport');
34587
+
34588
+ // Optional: stop observing once triggered
34589
+ // observer_outViewport.unobserve(entry.target);
34590
+ }
34591
+ });
34592
+ },
34593
+ {
34594
+ threshold: 0, // Trigger when element is completely out of view
34595
+ },
34596
+ );
34597
+
34598
+ let ui_job_id;
34599
+ $div.on('inViewport', function () {
34600
+ if ($div.children().length) {
34601
+ $div.removeClass('skeleton');
34602
+ return;
34603
+ }
34604
+
34605
+ // if (UI_WORKER_OBJ.cache[$div.attr('xu-ui-id')]) {
34606
+ // $div[0].style.removeProperty('height');
34607
+ // $div.removeClass('skeleton');
34608
+ // $div.html(UI_WORKER_OBJ.cache[$div.attr('xu-ui-id')]);
34609
+ // } else {
34610
+ hover_in($div);
34611
+ ui_job_id = func.UI.worker.add_to_queue(SESSION_ID, 'gui event', 'render_viewport', { $div, nodeP, parent_infoP, $root_container, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, $container }, null, null, paramsP.dsSessionP);
34612
+ // }
34613
+ observer_outViewport.observe($div[0]);
34614
+ });
34615
+
34616
+ $div.on('outViewport', function () {
34617
+ func.UI.worker.delete_job(SESSION_ID, ui_job_id);
34618
+
34619
+ if ($div.children().length) {
34620
+ // UI_WORKER_OBJ.cache[$div.attr('xu-ui-id')] = $div.children().clone(true);
34621
+ $div.empty();
34622
+ const height = $div?.data()?.xuData?.viewport_height || 10;
34623
+ if (typeof height !== 'undefined') {
34624
+ $div.css('height', height);
34625
+ }
34626
+ }
34627
+ // $div.addClass('skeleton');
34628
+ observer_inViewport.observe($div[0]);
34629
+ });
34630
+ $div.addClass('skeleton');
34631
+ observer_inViewport.observe($div[0]);
34632
+ };
34633
+ xu_viewport();
34634
+ } else {
34635
+ await iterate_child($div, nodeP, parent_infoP, $root_container);
34636
+ }
34637
+
34638
+ // const ret_iterate_child = await iterate_child($div, nodeP, parent_infoP, null, $root_container);
34639
+ return await done(ret);
34640
+ };
34641
+
34642
+ const draw_html_element = async function (element) {
34643
+ const done = async function (ret = {}) {
34644
+ const xu_ui_id = $div.attr('xu-ui-id');
34645
+ $div.removeClass('display_none');
34646
+ if (ret.has_xu_exp_render_attribute) {
34647
+ // $div.css('display', 'unset');
34648
+
34649
+ const xu_render_cache_id = await get_xu_render_cache_str(SESSION_ID, paramsP.dsSessionP, Object.keys($div.data()?.xuData?.attr_exp_info?.['xu-render']?.fields || {}));
34650
+ const _$div = $div.clone(true);
34651
+ UI_WORKER_OBJ.xu_render_cache[xu_ui_id + xu_render_cache_id] = { $div: _$div, paramsP, data: _$div.data() };
34652
+ nodeP.xu_render_xu_ui_id = xu_ui_id;
34653
+ nodeP.xu_render_cache_id = xu_render_cache_id;
34654
+
34655
+ if (ret.xu_render_background_processing) {
34656
+ temp_$div.remove();
34657
+ // $container.find(`[xu-ui-id="${xu_ui_id}"]`).remove();
34658
+ return $div;
34659
+ } else {
34660
+ // $div.css('display', 'unset');
34661
+ temp_$div.replaceWith($div);
34662
+ return $div;
34663
+ }
34664
+ } else {
34665
+ if (ret.has_xu_render_attribute) {
34666
+ temp_$div.remove();
34667
+ return $div;
34668
+ }
34669
+ // $div.css('display', 'unset');
34670
+ temp_$div.replaceWith($div);
34671
+ return $div;
34672
+ }
34673
+ };
34674
+ if (!element || element === 'script') return await done();
34675
+ let str = '';
34676
+
34677
+ var temp_$div = await func.UI.screen.create_container(SESSION_ID, $root_container, nodeP, $container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, prop, null, null, element, null, str, true);
34678
+
34679
+ let temp_$container = $('<tmp>').data('xuData', $container.data().xuData);
34680
+ let $div = temp_$div.clone(true);
34681
+
34682
+ // $div.css('display', 'none');
34683
+
34684
+ $div.hover(
34685
+ function (e) {
34686
+ hover_in($div, e);
34687
+ },
34688
+ function (e) {
34689
+ hover_out();
34690
+ },
34691
+ );
34692
+ if (paramsP.paramsP === 'grid' || parent_infoP?.iterate_info) {
34693
+ $div.on('click contextmenu', function (e) {
34694
+ hover_in($div, e);
34695
+ });
34696
+ }
34697
+
34698
+ let ret = await func.UI.screen.set_attributes_new(SESSION_ID, is_skeleton, $root_container, nodeP, temp_$container, paramsP, parent_infoP, jobNoP, keyP, parent_nodeP, $div, true);
34699
+ if (ret.abort || nodeP.tagName === 'svg' || !_.isEmpty(nodeP?.attributes?.['xu-text']) || !_.isEmpty(nodeP?.attributes?.['xu-html']) || !_.isEmpty(nodeP?.attributes?.['xu-exp:xu-text']) || !_.isEmpty(nodeP?.attributes?.['xu-exp:xu-html'])) {
34700
+ return await done(ret);
34701
+ }
34702
+ // check if iterator made to prevent children render
34703
+
34704
+ if (nodeP?.attributes?.['xu-viewport'] == 'true') {
34705
+ // const xu_viewport = async function () {
34706
+ // const data = { $div: $div.clone(true), nodeP, parent_infoP, $root_container, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, $container };
34707
+ // const container_id = $container.attr('xu-ui-id');
34708
+ // if (!UI_WORKER_OBJ.pending_for_viewport_render[container_id]) {
34709
+ // UI_WORKER_OBJ.pending_for_viewport_render[container_id] = { base_$div: $div, data: [], $container };
34710
+ // await iterate_child($div, nodeP, parent_infoP, $root_container);
34711
+ // } else {
34712
+ // $div.remove();
34713
+ // }
34714
+ // UI_WORKER_OBJ.pending_for_viewport_render[container_id].data.push(data);
34715
+
34716
+ // // if (!$div.children().length) {
34717
+ // // // render the first element to determine height
34718
+ // // await iterate_child($div, nodeP, parent_infoP, $root_container);
34719
+ // // // hover_in($div);
34720
+ // // // func.UI.worker.add_to_queue(SESSION_ID, 'gui event', 'render_viewport', data, null, null, paramsP.dsSessionP);
34721
+ // // } else {
34722
+ // // }
34723
+ // };
34724
+ const xu_viewport = function () {
34725
+ const observer_inViewport = new IntersectionObserver(
34726
+ function (entries) {
34727
+ entries.forEach((entry) => {
34728
+ if (entry.isIntersecting) {
34729
+ $(entry.target).trigger('inViewport');
34730
+
34731
+ // Optional: stop observing once triggered
34732
+ observer_inViewport.unobserve(entry.target);
34733
+ }
34734
+ });
34735
+ },
34736
+ {
34737
+ threshold: 0.1, // Trigger when 10% of element is visible
34738
+ },
34739
+ );
34740
+
34741
+ const observer_outViewport = new IntersectionObserver(
34742
+ function (entries) {
34743
+ entries.forEach((entry) => {
34744
+ if (!entry.isIntersecting) {
34745
+ // Element is OUT of viewport - trigger custom event
34746
+ $(entry.target).trigger('outViewport');
34747
+
34748
+ // Optional: stop observing once triggered
34749
+ // observer_outViewport.unobserve(entry.target);
34750
+ }
34751
+ });
34752
+ },
34753
+ {
34754
+ threshold: 0, // Trigger when element is completely out of view
34755
+ },
34756
+ );
34757
+
34758
+ let ui_job_id;
34759
+ $div.on('inViewport', function () {
34760
+ if ($div.children().length) {
34761
+ $div.removeClass('skeleton');
34762
+ return;
34763
+ }
34764
+
34765
+ // if (UI_WORKER_OBJ.cache[$div.attr('xu-ui-id')]) {
34766
+ // $div[0].style.removeProperty('height');
34767
+ // $div.removeClass('skeleton');
34768
+ // $div.html(UI_WORKER_OBJ.cache[$div.attr('xu-ui-id')]);
34769
+ // } else {
34770
+ hover_in($div);
34771
+ ui_job_id = func.UI.worker.add_to_queue(SESSION_ID, 'gui event', 'render_viewport', { $div, nodeP, parent_infoP, $root_container, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, temp_$container }, null, null, paramsP.dsSessionP);
34772
+ // }
34773
+ observer_outViewport.observe($div[0]);
34774
+ });
34775
+
34776
+ $div.on('outViewport', function () {
34777
+ func.UI.worker.delete_job(SESSION_ID, ui_job_id);
34778
+
34779
+ if ($div.children().length) {
34780
+ // UI_WORKER_OBJ.cache[$div.attr('xu-ui-id')] = $div.children().clone(true);
34781
+ $div.empty();
34782
+ const height = $div?.data()?.xuData?.viewport_height || 10;
34783
+ if (typeof height !== 'undefined') {
34784
+ $div.css('height', height);
34785
+ }
34786
+ }
34787
+ // $div.addClass('skeleton');
34788
+ observer_inViewport.observe($div[0]);
34789
+ });
34790
+ $div.addClass('skeleton');
34791
+ observer_inViewport.observe($div[0]);
34792
+ };
34793
+ xu_viewport();
34794
+ } else {
34795
+ // if (ret.xu_render_background_processing) {
34796
+ // // let temp_$div = $div.clone(true);
34797
+ // iterate_child($div, nodeP, parent_infoP, $root_container);
34798
+ // } else {
34799
+ // await iterate_child($div, nodeP, parent_infoP, $root_container);
34800
+ // }
34801
+ if (!ret.xu_render_background_processing) {
34802
+ iterate_child($div, nodeP, parent_infoP, $root_container);
34803
+ }
34804
+ }
34805
+
34806
+ // const ret_iterate_child = await iterate_child($div, nodeP, parent_infoP, null, $root_container);
34807
+ return await done(ret);
34808
+ };
34809
+
34810
+ if (nodeP.content && nodeP.attributes) {
34811
+ nodeP.attributes['xu-content'] = nodeP.content;
34812
+ }
34813
+
34814
+ if (nodeP.tagName === 'xu-widget') {
34815
+ if (is_skeleton) return;
34816
+ return await fx['widget']();
34817
+ }
34818
+ if (fx[nodeP.tagName]) {
34819
+ return await fx[nodeP.tagName]();
34820
+ }
34821
+ // const xu_viewport = async function () {
34822
+ // const data = { $div, nodeP, parent_infoP, $root_container, paramsP, jobNoP, is_skeleton, keyP, refreshed_ds, parent_nodeP, check_existP, $container };
34823
+ // const container_id = $container.attr('xu-ui-id');
34824
+ // if (!UI_WORKER_OBJ.pending_for_viewport_render[container_id]) {
34825
+ // UI_WORKER_OBJ.pending_for_viewport_render[container_id] = { base_$div: $div, data: [], $container };
34826
+ // await iterate_child($div, nodeP, parent_infoP, $root_container);
34827
+ // }
34828
+ // UI_WORKER_OBJ.pending_for_viewport_render[container_id].data.push(data);
34829
+ // };
34830
+
34831
+ // if (nodeP?.attributes?.['xu-viewport'] == 'true') {
34832
+ // return await xu_viewport();
34833
+ // } else {
34834
+ if (!glb.new_xu_render) {
34835
+ return await draw_html_element_org(nodeP.tagName);
34836
+ }
34837
+ return await draw_html_element(nodeP.tagName);
34838
+
34839
+ // }
34840
+ };
34841
+
34842
+ func.UI.screen.refresh_document_changes_for_realtime_update = async function (SESSION_ID, doc_change) {
34843
+ let _session = SESSION_OBJ[SESSION_ID];
34844
+ for (const [key, _ds] of Object.entries(_session.DS_GLB)) {
34845
+ let prog_obj = await func.utils.VIEWS_OBJ.get(SESSION_ID, _ds.prog_id);
34846
+ if (prog_obj?.progDataSource?.dataSourceRealtime && prog_obj?.progDataSource?.dataSourceTableId === doc_change.table_id) {
34847
+ try {
34848
+ // disabled in purpose to support create row
34849
+
34850
+ if (!_ds.screen_params) continue;
34851
+ if (_ds.screen_params.is_panelP) {
34852
+ func.UI.screen.refresh_screen(SESSION_ID, null, key);
34853
+ } else {
34854
+ func.action.execute(SESSION_ID, 'act_refresh', _ds, null, null);
34855
+ }
34856
+ } catch (err) {
34857
+ // console.error(err);
34858
+ }
34859
+ }
34860
+ }
34861
+
34862
+ if (glb.new_xu_render) {
34863
+ for (const [ui_cache_key, ui_cache_val] of Object.entries(UI_WORKER_OBJ.xu_render_cache)) {
34864
+ let prog_obj = await func.utils.VIEWS_OBJ.get(SESSION_ID, ui_cache_val.paramsP.prog_id);
34865
+ if (prog_obj?.progDataSource?.dataSourceTableId === doc_change.table_id) {
34866
+ ui_cache_val.$div = null;
34867
+ }
34868
+ }
34869
+ }
34870
+ };
34871
+
34872
+ const get_parent_ds_fields = function (SESSION_ID, dsSessionP) {
34873
+ var _session = SESSION_OBJ[SESSION_ID];
34874
+ var _ds = _session.DS_GLB[dsSessionP];
34875
+
34876
+ const idx = func.common.find_ROWID_idx(_ds, _ds.currentRecordId);
34877
+ const data = _ds.data_feed.rows[idx];
34878
+
34879
+ let obj = {};
34880
+
34881
+ if (typeof _ds.parentDataSourceNo !== 'undefined') {
34882
+ obj = get_parent_ds_fields(SESSION_ID, _ds.parentDataSourceNo);
34883
+ }
34884
+
34885
+ return { ...data, ...obj };
34886
+ };
34887
+
34888
+ const get_xu_render_cache_str = async function (SESSION_ID, dsSessionP, exclude_vars = []) {
34889
+ const fields_obj = get_parent_ds_fields(SESSION_ID, dsSessionP);
34890
+
34891
+ let str = '';
34892
+
34893
+ for (const [key, val] of Object.entries(fields_obj)) {
34894
+ if (exclude_vars.includes(key)) continue;
34895
+ str += typeof val !== 'undefined' ? JSON.stringify(val) : '';
34896
+ }
34897
+
34898
+ return 'C-' + (await func.common.sha256(str));
34899
+ };
34900
+ func.UI.component = {};
32689
34901
 
32690
34902
  func.UI.component.create_app_modal_component = function (
32691
34903
  SESSION_ID,