iobroker.javascript 10.0.0 → 10.1.1

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.
Files changed (180) hide show
  1. package/README.md +48 -12
  2. package/admin/assets/AiChatPanel-C_WbKMGX.js +242 -0
  3. package/admin/assets/AiDiffView-BtXbDWZ8.js +1 -0
  4. package/admin/assets/Debugger-DAdJnEhw.js +15 -0
  5. package/admin/assets/Error-DQ1pzKcf.js +1 -0
  6. package/admin/assets/Import-BjMtH6Gk.js +1 -0
  7. package/admin/assets/RulesEditor-dDRPHw4X.js +1 -0
  8. package/admin/assets/RulesEditor-k-DMHotH.css +1 -0
  9. package/admin/assets/{ScriptEditor-BGIuoNei.js → ScriptEditor-CZSc7rwE.js} +2 -2
  10. package/admin/assets/ScriptEditorVanillaMonaco-DEKg14_A.js +3 -0
  11. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-DPmwd_G2.js +1 -0
  12. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-C8inUeKt.js +1243 -0
  13. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-VcQjt7_9.js +9 -0
  14. package/admin/assets/aiPromptBuilder-D5FDo74i.js +1 -0
  15. package/admin/assets/blockly-DBw-ytY1.js +1047 -0
  16. package/admin/assets/blocks_action-BqfWEwpf.js +1 -0
  17. package/admin/assets/blocks_convert-CX0i-JfS.js +3 -0
  18. package/admin/assets/blocks_logic-D-QSzw95.js +1 -0
  19. package/admin/assets/blocks_number-D7JuNYsw.js +1 -0
  20. package/admin/assets/blocks_object-C9DzAlc7.js +1 -0
  21. package/admin/assets/blocks_procedures-BJMz6HWW.js +3 -0
  22. package/admin/assets/blocks_sendto-DRh7lk9o.js +5 -0
  23. package/admin/assets/blocks_switch-BfmboMex.js +2 -0
  24. package/admin/assets/blocks_system-B-78JfAc.js +1 -0
  25. package/admin/assets/blocks_text-CGbR0Ozw.js +1 -0
  26. package/admin/assets/blocks_time-5vS2geJg.js +1 -0
  27. package/admin/assets/blocks_timeout-BdaTywfN.js +1 -0
  28. package/admin/assets/blocks_trigger-D8kgHKbg.js +2 -0
  29. package/admin/assets/blocks_words-BhHIf_1o.js +1 -0
  30. package/admin/assets/{cronHoverProvider-pKJkSevo.js → cronHoverProvider-DpgESCox.js} +1 -1
  31. package/admin/assets/dist-CaOsN0XW.js +4 -0
  32. package/admin/assets/field_cron-B40zwSfJ.js +1 -0
  33. package/admin/assets/field_oid-KfoBnEM9.js +1 -0
  34. package/admin/assets/field_script-yXhe1iCp.js +1 -0
  35. package/admin/assets/helpers-B0ByElPJ.js +1 -0
  36. package/admin/assets/hostInit-9REPDUe7.js +1 -0
  37. package/admin/assets/index-07o_WKsX.js +726 -0
  38. package/admin/assets/index-Z8Hkv58g.css +1 -0
  39. package/admin/assets/{inlineChatWidget-ZaisTOLh.js → inlineChatWidget-B9y_gQcH.js} +2 -2
  40. package/admin/assets/{inlineDiffController-hTwHHqcc.js → inlineDiffController-C07CdIFo.js} +2 -2
  41. package/admin/assets/{mf-entry-bootstrap-0-d6052b31.js → mf-entry-bootstrap-0-efcb49d3.js} +7 -2
  42. package/admin/assets/stateHoverProvider-CqeoOjXs.js +9 -0
  43. package/admin/assets/{virtualExposes-Ed0lGq7k.js → virtualExposes-DgGB-18P.js} +1 -1
  44. package/admin/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__iobroker_javascript__remoteEntry_js-BwSvIKEV.js +1 -0
  45. package/admin/assets/virtual_mf-exposes___mfe_internal__iobroker_javascript__remoteEntry_js-ChiJXsfH.js +1 -0
  46. package/admin/custom/assets/Components-BCQTjBgm.js +1 -0
  47. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-BuAc8OyX.js +1 -0
  48. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-BGJv4zZP.js +1 -0
  49. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-CGb5Cofy.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_emotion_mf_1_styled__loadShare__.js-B4E6MFJ4.js} +1 -1
  50. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-BVCIAgbo.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-aRlxyEhq.js} +78 -78
  51. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-DQwzYx75.js +1494 -0
  52. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare__leaflet__loadShare__.js-h-rCw3iz.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare__leaflet__loadShare__.js-n2zIPi0L.js} +1 -1
  53. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-xxszBNje.js +9 -0
  54. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__prebuild__date_mf_2_fns__prebuild__-Cb5TR7FB.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__prebuild__date_mf_2_fns__prebuild__-Tq7tesSS.js} +1 -1
  55. package/admin/custom/assets/{_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__prebuild__leaflet__prebuild__-DARUoA03.js → _virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__prebuild__leaflet__prebuild__-BeF0jEWM.js} +1 -1
  56. package/admin/custom/assets/hostInit-CHwrowP4.js +1 -0
  57. package/admin/custom/assets/{index-uEKAoVT7.js → index-Cm6xl9K4.js} +1 -1
  58. package/admin/custom/assets/{lib-Yj8cfN0A.js → lib-bhrFL6jR.js} +1 -1
  59. package/admin/custom/assets/{mf-entry-bootstrap-0-77793feb.js → mf-entry-bootstrap-0-f08941e2.js} +7 -2
  60. package/admin/custom/assets/{setYear-DJ9FbdkO.js → setYear-DzTZ2h9A.js} +1 -1
  61. package/admin/custom/assets/virtualExposes-B5LJmnfO.js +1 -0
  62. package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-ML-chjs6.js +1 -0
  63. package/admin/custom/assets/virtual_mf-exposes___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-C3ImybiM.js +2 -0
  64. package/admin/custom/customComponents.js +12 -1
  65. package/admin/custom/i18n/de.json +11 -1
  66. package/admin/custom/i18n/en.json +11 -1
  67. package/admin/custom/i18n/es.json +11 -1
  68. package/admin/custom/i18n/fr.json +11 -1
  69. package/admin/custom/i18n/it.json +11 -1
  70. package/admin/custom/i18n/nl.json +11 -1
  71. package/admin/custom/i18n/pl.json +11 -1
  72. package/admin/custom/i18n/pt.json +11 -1
  73. package/admin/custom/i18n/ru.json +11 -1
  74. package/admin/custom/i18n/uk.json +11 -1
  75. package/admin/custom/i18n/zh-cn.json +11 -1
  76. package/admin/google-blockly/VERSION +1 -0
  77. package/admin/google-blockly/media/drop.mp3 +0 -0
  78. package/admin/google-blockly/msg/js/de.js +332 -56
  79. package/admin/google-blockly/msg/js/en.js +319 -43
  80. package/admin/google-blockly/msg/js/es.js +319 -42
  81. package/admin/google-blockly/msg/js/fr.js +315 -39
  82. package/admin/google-blockly/msg/js/it.js +327 -51
  83. package/admin/google-blockly/msg/js/nl.js +376 -100
  84. package/admin/google-blockly/msg/js/pl.js +318 -42
  85. package/admin/google-blockly/msg/js/pt.js +318 -42
  86. package/admin/google-blockly/msg/js/ru.js +320 -44
  87. package/admin/google-blockly/msg/js/uk.js +326 -50
  88. package/admin/google-blockly/msg/js/zh-cn.js +322 -46
  89. package/admin/i18n/de.json +51 -26
  90. package/admin/i18n/en.json +50 -25
  91. package/admin/i18n/es.json +51 -18
  92. package/admin/i18n/fr.json +50 -17
  93. package/admin/i18n/it.json +50 -17
  94. package/admin/i18n/nl.json +50 -17
  95. package/admin/i18n/pl.json +51 -18
  96. package/admin/i18n/pt.json +50 -17
  97. package/admin/i18n/ru.json +50 -17
  98. package/admin/i18n/uk.json +50 -17
  99. package/admin/i18n/zh-cn.json +50 -17
  100. package/admin/jsonConfig.json +398 -0
  101. package/admin/mf-manifest.json +1 -1
  102. package/admin/mf-stats.json +1 -1
  103. package/admin/remoteEntry.js +12 -1
  104. package/admin/tab.html +6 -98
  105. package/build/lib/javascript.d.ts +48 -0
  106. package/build/lib/mirror.js +9 -0
  107. package/build/lib/mirror.js.map +1 -1
  108. package/build/lib/sandbox.js +37 -0
  109. package/build/lib/sandbox.js.map +1 -1
  110. package/build/lib/secrets.js +220 -0
  111. package/build/lib/secrets.js.map +1 -0
  112. package/build/lib/typescriptSettings.js +112 -2
  113. package/build/lib/typescriptSettings.js.map +1 -1
  114. package/build/lib/typescriptTools.js +168 -43
  115. package/build/lib/typescriptTools.js.map +1 -1
  116. package/build/main.js +61 -5
  117. package/build/main.js.map +1 -1
  118. package/build/types.d.ts +48 -0
  119. package/docs/en/blockly.md +29 -0
  120. package/docs/en/javascript.md +72 -0
  121. package/docs/en/upgrade-guide.md +3 -0
  122. package/io-package.json +59 -28
  123. package/package.json +8 -3
  124. package/admin/assets/AiChatPanel-p0KAg6Cs.js +0 -237
  125. package/admin/assets/AiDiffView-BPTLnNx1.js +0 -1
  126. package/admin/assets/AiScriptAnalyzer--BHML2rN.js +0 -9
  127. package/admin/assets/BlocklyEditor-CAjVMhYT.js +0 -81
  128. package/admin/assets/ContextWrapper-BVc8wTK_.css +0 -1
  129. package/admin/assets/ContextWrapper-D9CrnNKs.js +0 -127
  130. package/admin/assets/Debugger-SjROokFI.js +0 -15
  131. package/admin/assets/Error-DDfrxAt2.js +0 -1
  132. package/admin/assets/Import-DpTg1Jow.js +0 -1
  133. package/admin/assets/RulesEditor-BSRFWpEm.css +0 -1
  134. package/admin/assets/RulesEditor-D0hgrcBc.js +0 -1
  135. package/admin/assets/ScriptEditorVanillaMonaco-DyMQtoTQ.js +0 -3
  136. package/admin/assets/_virtual_mf-localSharedImportMap___mfe_internal__iobroker_javascript__mf_owner__1-DWJotR1B.js +0 -1
  137. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__1__loadShare___mf_0_iobroker_mf_1_gui_mf_2_components__loadShare__.js-CxICLr5Z.js +0 -1243
  138. package/admin/assets/_virtual_mf___mfe_internal__iobroker_javascript__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-BBAXJaqI.js +0 -9
  139. package/admin/assets/aiCodeLensProvider-hyAmut0e.js +0 -4
  140. package/admin/assets/aiPromptBuilder-Bs27qOHT.js +0 -7
  141. package/admin/assets/blocklyDarkTheme-DEiAX5DT.js +0 -1
  142. package/admin/assets/dist-uw5orDgd.js +0 -4
  143. package/admin/assets/hostInit-BFg5u9hY.js +0 -1
  144. package/admin/assets/index-B1gICjdq.js +0 -192
  145. package/admin/assets/index-BHhhebRG.css +0 -1
  146. package/admin/assets/mjs-DWqivHEk.js +0 -90
  147. package/admin/assets/stateHoverProvider-C7DawIs-.js +0 -9
  148. package/admin/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__iobroker_javascript__remoteEntry_js-BYs71IQF.js +0 -1
  149. package/admin/assets/virtual_mf-exposes___mfe_internal__iobroker_javascript__remoteEntry_js-DnnXQRkG.js +0 -1
  150. package/admin/custom/assets/Components-BrDyDHXh.js +0 -1
  151. package/admin/custom/assets/_virtual_mf-localSharedImportMap___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1-CyYJM2-v.js +0 -1
  152. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_emotion_mf_1_react__loadShare__.js-BdzCssLn.js +0 -1
  153. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__.js-BkB0anQX.js +0 -1494
  154. package/admin/custom/assets/_virtual_mf___mfe_internal__ConfigCustomJavascriptSet__mf_owner__1__loadShare__react_mf_2_dom_mf_1_client__loadShare__.js-BotqDuw-.js +0 -9
  155. package/admin/custom/assets/hostInit-DJx2uXXy.js +0 -1
  156. package/admin/custom/assets/virtualExposes-CxDjLoYu.js +0 -1
  157. package/admin/custom/assets/virtual_mf-REMOTE_ENTRY_ID___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-BU-ugy_7.js +0 -1
  158. package/admin/custom/assets/virtual_mf-exposes-ssr___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-BEfZbrf7.js +0 -2
  159. package/admin/custom/assets/virtual_mf-exposes___mfe_internal__ConfigCustomJavascriptSet__customComponents_js-CTeZ0Jpm.js +0 -2
  160. package/admin/google-blockly/blockly_compressed.js +0 -1679
  161. package/admin/google-blockly/blocks_compressed.js +0 -193
  162. package/admin/google-blockly/javascript_compressed.js +0 -264
  163. package/admin/google-blockly/msg/messages.js +0 -1630
  164. package/admin/google-blockly/own/blocks_action.js +0 -765
  165. package/admin/google-blockly/own/blocks_convert.js +0 -480
  166. package/admin/google-blockly/own/blocks_logic.js +0 -459
  167. package/admin/google-blockly/own/blocks_number.js +0 -30
  168. package/admin/google-blockly/own/blocks_object.js +0 -402
  169. package/admin/google-blockly/own/blocks_procedures.js +0 -688
  170. package/admin/google-blockly/own/blocks_sendto.js +0 -702
  171. package/admin/google-blockly/own/blocks_switch.js +0 -257
  172. package/admin/google-blockly/own/blocks_system.js +0 -1409
  173. package/admin/google-blockly/own/blocks_text.js +0 -104
  174. package/admin/google-blockly/own/blocks_time.js +0 -639
  175. package/admin/google-blockly/own/blocks_timeout.js +0 -551
  176. package/admin/google-blockly/own/blocks_trigger.js +0 -1791
  177. package/admin/google-blockly/own/blocks_words.js +0 -708
  178. package/admin/google-blockly/own/field_cron.js +0 -158
  179. package/admin/google-blockly/own/field_oid.js +0 -642
  180. package/admin/google-blockly/own/field_script.js +0 -159
@@ -1,1791 +0,0 @@
1
- 'use strict';
2
-
3
- if (typeof goog !== 'undefined') {
4
- goog.provide('Blockly.JavaScript.Trigger');
5
- goog.require('Blockly.JavaScript');
6
- }
7
-
8
- Blockly.CustomBlocks = Blockly.CustomBlocks || [];
9
- Blockly.CustomBlocks.push('Trigger');
10
-
11
- Blockly.Trigger = {
12
- HUE: 330,
13
- blocks: {},
14
- WARNING_PARENTS: [
15
- 'on', 'on_ext', 'schedule', 'schedule_by_id', 'schedule_create', 'astro', 'onMessage', 'onFile', 'onLog', 'onEnumMembers', // trigger blocks
16
- 'timeouts_setinterval', 'timeouts_setinterval_variable', // timeouts
17
- 'controls_repeat_ext', 'controls_repeat_ext', 'controls_for', 'controls_forEach', // loops
18
- ],
19
- };
20
-
21
- // --- ON Extended-----------------------------------------------------------
22
-
23
- Blockly.Trigger.blocks['on_ext'] =
24
- '<block type="on_ext">' +
25
- ' <mutation items="1"></mutation>' +
26
- ' <field name="CONDITION">ne</field>' +
27
- ' <field name="ACK_CONDITION"></field>' +
28
- ' <value name="OID0">' +
29
- ' <shadow type="field_oid">' +
30
- ' </shadow>' +
31
- ' </value>' +
32
- '</block>';
33
-
34
- Blockly.Blocks['on_ext_oid_container'] = {
35
- /**
36
- * Mutator block for container.
37
- * @this Blockly.Block
38
- */
39
- init: function () {
40
- this.appendDummyInput()
41
- .appendField(Blockly.Translate('on_ext_on'));
42
-
43
- this.appendStatementInput('STACK');
44
-
45
- this.setColour(Blockly.Trigger.HUE);
46
-
47
- this.setTooltip(Blockly.Translate('on_ext_on_tooltip'));
48
- this.contextMenu = false;
49
- },
50
- };
51
-
52
- Blockly.Blocks['on_ext_oid'] = {
53
- /**
54
- * Mutator block for add items.
55
- * @this Blockly.Block
56
- */
57
- init: function () {
58
- this.appendDummyInput('OID')
59
- .appendField(Blockly.Translate('on_ext_oid'));
60
-
61
- this.setPreviousStatement(true);
62
- this.setNextStatement(true);
63
-
64
- this.setColour(Blockly.Trigger.HUE);
65
-
66
- this.setTooltip(Blockly.Translate('on_ext_oid_tooltip'));
67
-
68
- this.contextMenu = false;
69
- },
70
- };
71
-
72
- Blockly.Blocks['on_ext'] = {
73
- init: function () {
74
- this.itemCount_ = 1;
75
- this.setMutator(new Blockly.icons.MutatorIcon(['on_ext_oid'], this));
76
-
77
- this.setInputsInline(false);
78
- this.setPreviousStatement(true, null);
79
- this.setNextStatement(true, null);
80
-
81
- this.setColour(Blockly.Trigger.HUE);
82
-
83
- this.setTooltip(Blockly.Translate('on_ext_tooltip'));
84
- this.setHelpUrl(getHelp('on_help'));
85
- },
86
- /**
87
- * Create XML to represent number of text inputs.
88
- * @return {!Element} XML storage element.
89
- * @this Blockly.Block
90
- */
91
- mutationToDom: function () {
92
- const container = document.createElement('mutation');
93
- container.setAttribute('items', this.itemCount_);
94
-
95
- return container;
96
- },
97
- /**
98
- * Parse XML to restore the text inputs.
99
- * @param {!Element} xmlElement XML storage element.
100
- * @this Blockly.Block
101
- */
102
- domToMutation: function (xmlElement) {
103
- this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
104
- this.updateShape_();
105
- },
106
- /**
107
- * Populate the mutator's dialog with this block's components.
108
- * @param {!Blockly.Workspace} workspace Mutator's workspace.
109
- * @return {!Blockly.Block} Root block in mutator.
110
- * @this Blockly.Block
111
- */
112
- decompose: function (workspace) {
113
- const containerBlock = workspace.newBlock('on_ext_oid_container');
114
- containerBlock.initSvg();
115
-
116
- let connection = containerBlock.getInput('STACK').connection;
117
- for (let i = 0; i < this.itemCount_; i++) {
118
- const itemBlock = workspace.newBlock('on_ext_oid');
119
- itemBlock.initSvg();
120
- connection.connect(itemBlock.previousConnection);
121
- connection = itemBlock.nextConnection;
122
- }
123
-
124
- return containerBlock;
125
- },
126
- /**
127
- * Reconfigure this block based on the mutator dialog's components.
128
- * @param {!Blockly.Block} containerBlock Root block in mutator.
129
- * @this Blockly.Block
130
- */
131
- compose: function (containerBlock) {
132
- let itemBlock = containerBlock.getInputTargetBlock('STACK');
133
- // Count number of inputs.
134
- const connections = [];
135
- while (itemBlock) {
136
- connections.push(itemBlock.valueConnection_);
137
- itemBlock = itemBlock.nextConnection &&
138
- itemBlock.nextConnection.targetBlock();
139
- }
140
-
141
- // Disconnect any children that don't belong.
142
- for (let k = 0; k < this.itemCount_; k++) {
143
- try {
144
- const connection = this.getInput('OID' + k).connection.targetConnection;
145
- if (connection && !connections.includes(connection)) {
146
- connection.disconnect();
147
- }
148
- } catch (e) {
149
- // Do nothing, input does not exist
150
- }
151
- }
152
-
153
- this.itemCount_ = connections.length;
154
- if (this.itemCount_ < 1) {
155
- this.itemCount_ = 1;
156
- }
157
- this.updateShape_();
158
-
159
- // Reconnect any child blocks.
160
- for (let i = 0; i < this.itemCount_; i++) {
161
- Blockly.icons.MutatorIcon.reconnect(connections[i], this, 'OID' + i);
162
- }
163
- },
164
- /**
165
- * Store pointers to any connected child blocks.
166
- * @param {!Blockly.Block} containerBlock Root block in mutator.
167
- * @this Blockly.Block
168
- */
169
- saveConnections: function (containerBlock) {
170
- let itemBlock = containerBlock.getInputTargetBlock('STACK');
171
- let i = 0;
172
-
173
- while (itemBlock) {
174
- let input;
175
- try {
176
- input = this.getInput('OID' + i);
177
- } catch (e) {
178
- input = null;
179
- }
180
- itemBlock.valueConnection_ = input?.connection.targetConnection;
181
- i++;
182
- itemBlock = itemBlock.nextConnection?.targetBlock();
183
- }
184
- },
185
- /**
186
- * Modify this block to have the correct number of inputs.
187
- * @private
188
- * @this Blockly.Block
189
- */
190
- updateShape_: function () {
191
- let conditionValue = undefined;
192
- try {
193
- if (this.getInput('CONDITION')) {
194
- conditionValue = this.getFieldValue('CONDITION');
195
- this.removeInput('CONDITION');
196
- }
197
- } catch (e) {
198
- // Do nothing, input does not exist
199
- }
200
-
201
-
202
- let conditionAckValue = undefined;
203
- try {
204
- if (this.getInput('ACK_CONDITION')) {
205
- conditionAckValue = this.getFieldValue('ACK_CONDITION');
206
- this.removeInput('ACK_CONDITION');
207
- }
208
- } catch (e) {
209
- // Do nothing, input does not exist
210
- }
211
-
212
- let input;
213
-
214
- for (let j = 0; input = this.inputList[j]; j++) {
215
- if (input.name === 'STATEMENT') {
216
- this.inputList.splice(j, 1);
217
- break;
218
- }
219
- }
220
-
221
- // Add new inputs.
222
- const wp = this.workspace;
223
-
224
- let i;
225
- for (i = 0; i < this.itemCount_; i++) {
226
- let _input;
227
- try {
228
- _input = this.getInput('OID' + i);
229
- } catch (e) {
230
- // Do nothing, input does not exist
231
- }
232
- if (!_input) {
233
- _input = this.appendValueInput('OID' + i);
234
-
235
- if (i === 0) {
236
- _input.appendField(Blockly.Translate('on_ext'));
237
- }
238
- setTimeout(__input => {
239
- if (!__input.connection.isConnected()) {
240
- const shadow = wp.newBlock('field_oid');
241
- shadow.setShadow(true);
242
- shadow.outputConnection.connect(__input.connection);
243
- shadow.initSvg();
244
- shadow.render();
245
- }
246
- }, 100, _input);
247
- } else {
248
- setTimeout(__input => {
249
- if (!__input.connection.isConnected()) {
250
- const shadow = wp.newBlock('field_oid');
251
- shadow.setShadow(true);
252
- shadow.outputConnection.connect(__input.connection);
253
- shadow.initSvg();
254
- shadow.render();
255
- }
256
- }, 100, _input);
257
- }
258
- }
259
-
260
- // Remove deleted inputs.
261
- try {
262
- while (this.getInput('OID' + i)) {
263
- this.removeInput('OID' + i);
264
- i++;
265
- }
266
- } catch (e) {
267
- // Do nothing, input does not exist
268
- }
269
-
270
- this.appendDummyInput('CONDITION')
271
- .appendField(new Blockly.FieldDropdown([
272
- [Blockly.Translate('on_onchange'), 'ne'],
273
- [Blockly.Translate('on_any'), 'any'],
274
- [Blockly.Translate('on_gt'), 'gt'],
275
- [Blockly.Translate('on_ge'), 'ge'],
276
- [Blockly.Translate('on_lt'), 'lt'],
277
- [Blockly.Translate('on_le'), 'le'],
278
- [Blockly.Translate('on_true'), 'true'],
279
- [Blockly.Translate('on_false'), 'false'],
280
- ]), 'CONDITION');
281
- if (conditionValue) {
282
- this.setFieldValue(conditionValue, 'CONDITION'); // restore previous value
283
- }
284
-
285
- this.appendDummyInput('ACK_CONDITION')
286
- .appendField(Blockly.Translate('on_ack'))
287
- .appendField(new Blockly.FieldDropdown([
288
- [Blockly.Translate('on_ack_any'), ''],
289
- [Blockly.Translate('on_ack_true'), 'true'],
290
- [Blockly.Translate('on_ack_false'), 'false'],
291
- ]), 'ACK_CONDITION');
292
- if (conditionAckValue) {
293
- this.setFieldValue(conditionAckValue, 'ACK_CONDITION'); // restore previous value
294
- }
295
-
296
- if (input) {
297
- this.inputList.push(input);
298
- } else {
299
- this.appendStatementInput('STATEMENT')
300
- .setCheck(null);
301
- }
302
- },
303
- /**
304
- * Called whenever anything on the workspace changes.
305
- * Add warning if this flow block is not nested inside a loop.
306
- * @param {!Blockly.Events.Abstract} e Change event.
307
- * @this Blockly.Block
308
- */
309
- onchange: function (e) {
310
- let legal = true;
311
-
312
- // Is the block nested in a trigger?
313
- let block = this;
314
- while (block = block.getSurroundParent()) {
315
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
316
- legal = false;
317
- break;
318
- }
319
- }
320
-
321
- if (legal) {
322
- this.setWarningText(null, this.id);
323
- } else {
324
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
325
- }
326
- },
327
- };
328
- Blockly.JavaScript.forBlock['on_ext'] = function (block) {
329
- const fCondition = block.getFieldValue('CONDITION');
330
- const fAckCondition = block.getFieldValue('ACK_CONDITION');
331
-
332
- let val;
333
- if (fCondition === 'true' || fCondition === 'false') {
334
- val = `val: ${fCondition}`;
335
- } else {
336
- val = `change: '${fCondition}'`;
337
- }
338
-
339
- const oids = [];
340
- for (let n = 0; n < block.itemCount_; n++) {
341
- let id = Blockly.JavaScript.valueToCode(block, 'OID' + n, Blockly.JavaScript.ORDER_COMMA);
342
- if (id) {
343
- id = id.toString();
344
- if (id.startsWith('\'') && id.endsWith('\'')) {
345
- id = `[${id}]`;
346
- }
347
- if (oids.indexOf(id) === -1) {
348
- oids.push(id);
349
- }
350
- }
351
- }
352
-
353
- const oid = `[].concat(${oids.join(').concat(')})`;
354
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
355
-
356
- return `on({ id: ${oid}, ${val}${fAckCondition ? `, ack: ${fAckCondition}` : ''} }, async (obj) => {\n` +
357
- (oids.length === 1 ? Blockly.JavaScript.prefixLines('let value = obj.state.val;\nlet oldValue = obj.oldState.val;', Blockly.JavaScript.INDENT) + '\n' : '') +
358
- statement +
359
- '});\n';
360
- };
361
-
362
- // --- ON -----------------------------------------------------------
363
- Blockly.Trigger.blocks['on'] =
364
- '<sep gap="5"></sep>' +
365
- '<block type="on">' +
366
- ' <field name="CONDITION">ne</field>' +
367
- ' <field name="ACK_CONDITION"></field>' +
368
- '</block>';
369
-
370
- Blockly.Blocks['on'] = {
371
- init: function () {
372
- this.appendDummyInput()
373
- .appendField(Blockly.Translate('on'));
374
-
375
- this.appendDummyInput('OID')
376
- .appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'OID');
377
-
378
- this.appendDummyInput('CONDITION')
379
- .appendField(new Blockly.FieldDropdown([
380
- [Blockly.Translate('on_onchange'), 'ne'],
381
- [Blockly.Translate('on_any'), 'any'],
382
- [Blockly.Translate('on_gt'), 'gt'],
383
- [Blockly.Translate('on_ge'), 'ge'],
384
- [Blockly.Translate('on_lt'), 'lt'],
385
- [Blockly.Translate('on_le'), 'le'],
386
- [Blockly.Translate('on_true'), 'true'],
387
- [Blockly.Translate('on_false'), 'false'],
388
- ]), 'CONDITION');
389
-
390
- this.appendDummyInput('ACK_CONDITION')
391
- .appendField(Blockly.Translate('on_ack'))
392
- .appendField(new Blockly.FieldDropdown([
393
- [Blockly.Translate('on_ack_any'), ''],
394
- [Blockly.Translate('on_ack_true'), 'true'],
395
- [Blockly.Translate('on_ack_false'), 'false'],
396
- ]), 'ACK_CONDITION');
397
-
398
- this.appendStatementInput('STATEMENT')
399
- .setCheck(null);
400
-
401
- this.setInputsInline(false);
402
- this.setPreviousStatement(true, null);
403
- this.setNextStatement(true, null);
404
-
405
- this.setColour(Blockly.Trigger.HUE);
406
-
407
- this.setTooltip(Blockly.Translate('on_tooltip'));
408
- this.setHelpUrl(getHelp('on_help'));
409
- },
410
- /**
411
- * Called whenever anything on the workspace changes.
412
- * Add warning if this flow block is not nested inside a loop.
413
- * @param {!Blockly.Events.Abstract} e Change event.
414
- * @this Blockly.Block
415
- */
416
- onchange: function (e) {
417
- let legal = true;
418
-
419
- // Is the block nested in a trigger?
420
- let block = this;
421
- while (block = block.getSurroundParent()) {
422
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
423
- legal = false;
424
- break;
425
- }
426
- }
427
-
428
- if (legal) {
429
- this.setWarningText(null, this.id);
430
- } else {
431
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
432
- }
433
- },
434
- };
435
- Blockly.JavaScript.forBlock['on'] = function (block) {
436
- const fObjId = block.getFieldValue('OID');
437
- const fCondition = block.getFieldValue('CONDITION');
438
- const fAckCondition = block.getFieldValue('ACK_CONDITION');
439
-
440
- Blockly.Msg.VARIABLES_DEFAULT_NAME = 'value';
441
-
442
- let val;
443
- if (fCondition === 'true' || fCondition === 'false') {
444
- val = `val: ${fCondition}`;
445
- } else {
446
- val = `change: '${fCondition}'`;
447
- }
448
-
449
- let objectName = main.objects[fObjId] && main.objects[fObjId].common && main.objects[fObjId].common.name ? main.objects[fObjId].common.name : '';
450
- if (typeof objectName === 'object') {
451
- objectName = objectName[systemLang] || objectName.en;
452
- }
453
-
454
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
455
-
456
- return `on({ id: '${fObjId}'${objectName ? ` /* ${objectName} */` : ''}, ${val}${fAckCondition ? `, ack: ${fAckCondition}` : ''} }, async (obj) => {\n` +
457
- Blockly.JavaScript.prefixLines('let value = obj.state.val;', Blockly.JavaScript.INDENT) + '\n' +
458
- Blockly.JavaScript.prefixLines('let oldValue = obj.oldState.val;', Blockly.JavaScript.INDENT) + '\n' +
459
- statement +
460
- '});\n';
461
- };
462
-
463
- // --- get info about event -----------------------------------------------------------
464
- Blockly.Trigger.blocks['on_source'] =
465
- '<sep gap="5"></sep>' +
466
- '<block type="on_source">' +
467
- ' <field name="ATTR">state.val</field>' +
468
- '</block>';
469
-
470
- Blockly.Blocks['on_source'] = {
471
- /**
472
- * Block for conditionally returning a value from a procedure.
473
- * @this Blockly.Block
474
- */
475
- init: function () {
476
- this.appendDummyInput()
477
- .appendField('↪');
478
-
479
- this.appendDummyInput('ATTR')
480
- .appendField(new Blockly.FieldDropdown([
481
- [Blockly.Translate('on_source_state_val'), 'state.val'],
482
- [Blockly.Translate('on_source_state_ts'), 'state.ts'],
483
- [Blockly.Translate('on_source_state_q'), 'state.q'],
484
- [Blockly.Translate('on_source_state_from'), 'state.from'],
485
- [Blockly.Translate('on_source_state_ack'), 'state.ack'],
486
- [Blockly.Translate('on_source_state_lc'), 'state.lc'],
487
- [Blockly.Translate('on_source_state_c'), 'state.c'],
488
- [Blockly.Translate('on_source_state_user'), 'state.user'],
489
- [Blockly.Translate('on_source_id'), 'id'],
490
- [Blockly.Translate('on_source_name'), 'common.name'],
491
- [Blockly.Translate('on_source_desc'), 'common.desc'],
492
- [Blockly.Translate('on_source_channel_id'), 'channelId'],
493
- [Blockly.Translate('on_source_channel_name'), 'channelName'],
494
- [Blockly.Translate('on_source_device_id'), 'deviceId'],
495
- [Blockly.Translate('on_source_device_name'), 'deviceName'],
496
- [Blockly.Translate('on_source_oldstate_val'), 'oldState.val'],
497
- [Blockly.Translate('on_source_oldstate_ts'), 'oldState.ts'],
498
- [Blockly.Translate('on_source_oldstate_q'), 'oldState.q'],
499
- [Blockly.Translate('on_source_oldstate_from'), 'oldState.from'],
500
- [Blockly.Translate('on_source_oldstate_ack'), 'oldState.ack'],
501
- [Blockly.Translate('on_source_oldstate_lc'), 'oldState.lc'],
502
- [Blockly.Translate('on_source_oldstate_c'), 'oldState.c'],
503
- [Blockly.Translate('on_source_oldstate_user'), 'oldState.user'],
504
- ]), 'ATTR');
505
-
506
- this.setInputsInline(true);
507
- this.setOutput(true);
508
-
509
- this.setColour(Blockly.Trigger.HUE);
510
-
511
- this.setTooltip(Blockly.Translate('on_source_tooltip'));
512
- this.setHelpUrl(getHelp('on_help'));
513
- },
514
- /**
515
- * Called whenever anything on the workspace changes.
516
- * Add warning if this flow block is not nested inside a loop.
517
- * @param {!Blockly.Events.Abstract} e Change event.
518
- * @this Blockly.Block
519
- */
520
- onchange: function (e) {
521
- let legal = false;
522
- // Is the block nested in a trigger?
523
- let block = this;
524
- do {
525
- if (this.FUNCTION_TYPES.includes(block.type)) {
526
- legal = true;
527
- break;
528
- }
529
- block = block.getSurroundParent();
530
- } while (block);
531
-
532
- if (legal) {
533
- this.setWarningText(null, this.id);
534
- } else {
535
- this.setWarningText(Blockly.Translate('on_source_warning'), this.id);
536
- }
537
- },
538
- /**
539
- * List of block types that are functions and thus do not need warnings.
540
- * To add a new function type add this to your code:
541
- * Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
542
- */
543
- FUNCTION_TYPES: ['on', 'on_ext', 'onEnumMembers'],
544
- };
545
- Blockly.JavaScript.forBlock['on_source'] = function (block) {
546
- let fAttr = block.getFieldValue('ATTR');
547
- const parts = fAttr.split('.');
548
-
549
- if (parts.length > 1) {
550
- fAttr = `(obj.${parts[0]} ? obj.${fAttr} : '')`;
551
- } else {
552
- fAttr = `obj.${fAttr}`;
553
- }
554
-
555
- return [fAttr, Blockly.JavaScript.ORDER_ATOMIC];
556
- };
557
-
558
- // --- acknowledge -----------------------------------------------------------
559
- Blockly.Trigger.blocks['on_ack_value'] =
560
- '<sep gap="5"></sep>' +
561
- '<block type="on_ack_value">' +
562
- '</block>';
563
-
564
- Blockly.Blocks['on_ack_value'] = {
565
- /**
566
- * Block for conditionally returning a value from a procedure.
567
- * @this Blockly.Block
568
- */
569
- init: function () {
570
- this.appendDummyInput()
571
- .appendField('↪ ' + Blockly.Translate('on_ack_value'));
572
-
573
- this.setInputsInline(false);
574
- this.setPreviousStatement(true, null);
575
- this.setNextStatement(true, null);
576
-
577
- this.setColour(Blockly.Trigger.HUE);
578
-
579
- this.setTooltip(Blockly.Translate('on_ack_value_tooltip'));
580
- this.setHelpUrl(getHelp('on_help'));
581
- },
582
- /**
583
- * Called whenever anything on the workspace changes.
584
- * Add warning if this flow block is not nested inside a loop.
585
- * @param {!Blockly.Events.Abstract} e Change event.
586
- * @this Blockly.Block
587
- */
588
- onchange: function (e) {
589
- let legal = false;
590
- // Is the block nested in a trigger?
591
- let block = this;
592
- do {
593
- if (this.FUNCTION_TYPES.includes(block.type)) {
594
- legal = true;
595
- break;
596
- }
597
- block = block.getSurroundParent();
598
- } while (block);
599
-
600
- if (legal) {
601
- this.setWarningText(null, this.id);
602
- } else {
603
- this.setWarningText(Blockly.Translate('on_ack_value_warning'), this.id);
604
- }
605
- },
606
- /**
607
- * List of block types that are functions and thus do not need warnings.
608
- * To add a new function type add this to your code:
609
- * Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
610
- */
611
- FUNCTION_TYPES: ['on', 'on_ext', 'onEnumMembers'],
612
- };
613
- Blockly.JavaScript.forBlock['on_ack_value'] = function (block) {
614
- return 'if (obj.id && obj?.state && !obj.state.ack) {\n' +
615
- Blockly.JavaScript.prefixLines(`await setStateAsync(obj.id, { val: obj.state.val, ack: true });`, Blockly.JavaScript.INDENT) + '\n' +
616
- `}\n`;
617
- };
618
-
619
- // --- ASTRO -----------------------------------------------------------
620
- Blockly.Trigger.blocks['astro'] =
621
- '<block type="astro">' +
622
- ' <field name="TYPE">sunrise</field>' +
623
- ' <field name="OFFSET">0</field>' +
624
- '</block>';
625
-
626
- Blockly.Blocks['astro'] = {
627
- init: function () {
628
- this.appendDummyInput()
629
- .appendField(Blockly.Translate('astro'));
630
-
631
- this.appendDummyInput('TYPE')
632
- .appendField(new Blockly.FieldDropdown([
633
- [Blockly.Translate('astro_sunriseText'), 'sunrise'],
634
- [Blockly.Translate('astro_sunriseEndText'), 'sunriseEnd'],
635
- [Blockly.Translate('astro_goldenHourEndText'), 'goldenHourEnd'],
636
- [Blockly.Translate('astro_solarNoonText'), 'solarNoon'],
637
- [Blockly.Translate('astro_goldenHourText'), 'goldenHour'],
638
- [Blockly.Translate('astro_sunsetStartText'), 'sunsetStart'],
639
- [Blockly.Translate('astro_sunsetText'), 'sunset'],
640
- [Blockly.Translate('astro_duskText'), 'dusk'],
641
- [Blockly.Translate('astro_nauticalDuskText'), 'nauticalDusk'],
642
- [Blockly.Translate('astro_nightText'), 'night'],
643
- [Blockly.Translate('astro_nightEndText'), 'nightEnd'],
644
- [Blockly.Translate('astro_nauticalDawnText'), 'nauticalDawn'],
645
- [Blockly.Translate('astro_dawnText'), 'dawn'],
646
- [Blockly.Translate('astro_nadirText'), 'nadir'],
647
- ]), 'TYPE');
648
-
649
- this.appendDummyInput()
650
- .appendField(Blockly.Translate('astro_offset'));
651
-
652
- this.appendDummyInput('OFFSET')
653
- .appendField(new Blockly.FieldTextInput('0'), 'OFFSET');
654
-
655
- this.appendDummyInput()
656
- .appendField(Blockly.Translate('astro_minutes'));
657
-
658
- this.appendStatementInput('STATEMENT')
659
- .setCheck(null);
660
-
661
- this.setInputsInline(true);
662
- this.setPreviousStatement(true, null);
663
- this.setNextStatement(true, null);
664
-
665
- this.setColour(Blockly.Trigger.HUE);
666
-
667
- this.setTooltip(Blockly.Translate('astro_tooltip'));
668
- this.setHelpUrl(getHelp('astro_help'));
669
- },
670
- /**
671
- * Called whenever anything on the workspace changes.
672
- * Add warning if this flow block is not nested inside a loop.
673
- * @param {!Blockly.Events.Abstract} e Change event.
674
- * @this Blockly.Block
675
- */
676
- onchange: function (e) {
677
- let legal = true;
678
-
679
- // Is the block nested in a trigger?
680
- let block = this;
681
- while (block = block.getSurroundParent()) {
682
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
683
- legal = false;
684
- break;
685
- }
686
- }
687
-
688
- if (legal) {
689
- this.setWarningText(null, this.id);
690
- } else {
691
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
692
- }
693
- },
694
- };
695
- Blockly.JavaScript.forBlock['astro'] = function (block) {
696
- const fType = block.getFieldValue('TYPE');
697
- const fOffset = parseInt(block.getFieldValue('OFFSET'), 10);
698
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
699
-
700
- return `schedule({ astro: '${fType}', shift: ${fOffset} }, async () => {\n` +
701
- statement +
702
- '});\n';
703
- };
704
-
705
- // --- SCHEDULE -----------------------------------------------------------
706
- Blockly.Trigger.blocks['schedule'] =
707
- '<block type="schedule">' +
708
- ' <field name="SCHEDULE">* * * * *</field>' +
709
- '</block>';
710
-
711
- Blockly.Blocks['schedule'] = {
712
- init: function () {
713
- this.appendDummyInput()
714
- .appendField(Blockly.Translate('schedule'));
715
-
716
- this.appendDummyInput('SCHEDULE')
717
- .appendField(new Blockly.FieldCRON('* * * * *'), 'SCHEDULE');
718
-
719
- this.appendStatementInput('STATEMENT')
720
- .setCheck(null);
721
-
722
- this.setInputsInline(false);
723
- this.setPreviousStatement(true, null);
724
- this.setNextStatement(true, null);
725
-
726
- this.setColour(Blockly.Trigger.HUE);
727
-
728
- this.setTooltip(Blockly.Translate('schedule_tooltip'));
729
- this.setHelpUrl(getHelp('schedule_help'));
730
- },
731
- /**
732
- * Called whenever anything on the workspace changes.
733
- * Add warning if this flow block is not nested inside a loop.
734
- * @param {!Blockly.Events.Abstract} e Change event.
735
- * @this Blockly.Block
736
- */
737
- onchange: function (e) {
738
- let legal = true;
739
-
740
- // Is the block nested in a trigger?
741
- let block = this;
742
- while (block = block.getSurroundParent()) {
743
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
744
- legal = false;
745
- break;
746
- }
747
- }
748
-
749
- if (legal) {
750
- this.setWarningText(null, this.id);
751
- } else {
752
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
753
- }
754
- },
755
- };
756
- Blockly.JavaScript.forBlock['schedule'] = function (block) {
757
- let fSchedule = block.getFieldValue('SCHEDULE');
758
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
759
-
760
- if (fSchedule.startsWith('{')) {
761
- fSchedule = `'${fSchedule}'`;
762
- } else {
763
- fSchedule = `"${fSchedule}"`;
764
- }
765
-
766
- return `schedule(${fSchedule}, async () => {\n` +
767
- statement +
768
- '});\n';
769
- };
770
-
771
- // --- SCHEDULE BY ID -----------------------------------------------------
772
- Blockly.Trigger.blocks['schedule_by_id'] =
773
- '<block type="schedule_by_id">' +
774
- ' <field name="ACK_CONDITION"></field>' +
775
- '</block>';
776
-
777
- Blockly.Blocks['schedule_by_id'] = {
778
- init: function () {
779
- this.appendDummyInput()
780
- .appendField(Blockly.Translate('schedule_by_id'));
781
-
782
- this.appendDummyInput('OID')
783
- .appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'state'), 'OID');
784
-
785
- this.appendDummyInput('ACK_CONDITION')
786
- .appendField(Blockly.Translate('on_ack'))
787
- .appendField(new Blockly.FieldDropdown([
788
- [Blockly.Translate('on_ack_any'), ''],
789
- [Blockly.Translate('on_ack_true'), 'true'],
790
- [Blockly.Translate('on_ack_false'), 'false'],
791
- ]), 'ACK_CONDITION');
792
-
793
- this.appendStatementInput('STATEMENT')
794
- .setCheck(null);
795
-
796
- this.setInputsInline(false);
797
- this.setPreviousStatement(true, null);
798
- this.setNextStatement(true, null);
799
-
800
- this.setColour(Blockly.Trigger.HUE);
801
-
802
- this.setTooltip(Blockly.Translate('schedule_by_id_tooltip'));
803
- this.setHelpUrl(getHelp('schedule_by_id_help'));
804
- },
805
- };
806
- Blockly.JavaScript.forBlock['schedule_by_id'] = function (block) {
807
- const fObjId = block.getFieldValue('OID');
808
- const fAckCondition = block.getFieldValue('ACK_CONDITION');
809
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
810
-
811
- let objectName = main.objects[fObjId] && main.objects[fObjId].common && main.objects[fObjId].common.name ? main.objects[fObjId].common.name : '';
812
- if (typeof objectName === 'object') {
813
- objectName = objectName[systemLang] || objectName.en;
814
- }
815
-
816
- return `scheduleById('${fObjId}'${objectName ? ` /* ${objectName} */` : ''}${fAckCondition ? `, ${fAckCondition}` : ''}, async () => {\n` +
817
- statement +
818
- '});\n';
819
- };
820
-
821
- // --- set named schedule -----------------------------------------------------------
822
- Blockly.Trigger.blocks['schedule_create'] =
823
- '<block type="schedule_create">' +
824
- ' <field name="NAME">schedule</field>' +
825
- ' <value name="SCHEDULE">' +
826
- ' <shadow type="field_cron">' +
827
- ' </shadow>' +
828
- ' </value>' +
829
- '</block>';
830
- /**
831
- * Ensure two identically-named procedures don't exist.
832
- * @param {string} name Proposed procedure name.
833
- * @param {!Blockly.Block} block Block to disambiguate.
834
- * @return {string} Non-colliding name.
835
- */
836
- Blockly.Trigger.findLegalName = function (name, block) {
837
- if (block.isInFlyout) {
838
- // Flyouts can have multiple procedures called 'do something'.
839
- return name;
840
- }
841
- while (!Blockly.Trigger.isLegalName_(name, block.workspace, block)) {
842
- // Collision with another procedure.
843
- const r = name.match(/^(.*?)(\d+)$/);
844
- if (!r) {
845
- name += '1';
846
- } else {
847
- name = r[1] + (parseInt(r[2], 10) + 1);
848
- }
849
- }
850
- return name;
851
- };
852
-
853
- /**
854
- * Does this procedure have a legal name? Illegal names include names of
855
- * procedures already defined.
856
- * @param {string} name The questionable name.
857
- * @param {!Blockly.Workspace} workspace The workspace to scan for collisions.
858
- * @param {Blockly.Block=} opt_exclude Optional block to exclude from
859
- * comparisons (one doesn't want to collide with oneself).
860
- * @return {boolean} True if the name is legal.
861
- * @private
862
- */
863
- Blockly.Trigger.isLegalName_ = function (name, workspace, opt_exclude) {
864
- if (name === 'schedule') {
865
- return false;
866
- }
867
-
868
- const blocks = workspace.getAllBlocks();
869
- // Iterate through every block and check the name.
870
- for (let i = 0; i < blocks.length; i++) {
871
- if (blocks[i] == opt_exclude) {
872
- continue;
873
- }
874
- if (blocks[i].isSchedule_) {
875
- const blockName = blocks[i].getFieldValue('NAME');
876
- if (Blockly.Names.equals(blockName, name)) {
877
- return false;
878
- }
879
- }
880
- }
881
- return true;
882
- };
883
- /**
884
- * Rename a procedure. Called by the editable field.
885
- * @param {string} name The proposed new name.
886
- * @return {string} The accepted name.
887
- * @this {!Blockly.Field}
888
- */
889
- Blockly.Trigger.rename = function (name) {
890
- // Strip leading and trailing whitespace. Beyond this, all names are legal.
891
- name = name.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
892
-
893
- return Blockly.Trigger.findLegalName(name, this.sourceBlock_);
894
- };
895
-
896
- Blockly.Blocks['schedule_create'] = {
897
- init: function () {
898
- const nameField = new Blockly.FieldTextInput(
899
- Blockly.Trigger.findLegalName('schedule', this),
900
- Blockly.Trigger.rename);
901
-
902
- nameField.setSpellcheck(false);
903
-
904
- this.appendDummyInput('NAME')
905
- .appendField(Blockly.Translate('schedule_create'))
906
- .appendField(nameField, 'NAME');
907
-
908
- this.appendValueInput('SCHEDULE')
909
- .appendField(Blockly.Translate('schedule_text'));
910
-
911
- this.appendStatementInput('STATEMENT')
912
- .setCheck(null);
913
-
914
- this.setInputsInline(false);
915
- this.setPreviousStatement(true, null);
916
- this.setNextStatement(true, null);
917
-
918
- this.setColour(Blockly.Trigger.HUE);
919
-
920
- this.setTooltip(Blockly.Translate('schedule_create_tooltip'));
921
- this.setHelpUrl(getHelp('schedule_create_help'));
922
- },
923
- isSchedule_: true,
924
- getVars: function () {
925
- return [this.getFieldValue('NAME')];
926
- },
927
- getVarModels: function () {
928
- const name = this.getFieldValue('NAME');
929
- return [{ getId: () => name, name: name, type: 'cron' }];
930
- },
931
- };
932
-
933
- Blockly.JavaScript.forBlock['schedule_create'] = function (block) {
934
- const fName = Blockly.JavaScript.nameDB_.safeName(block.getFieldValue('NAME'));
935
- const vSchedule = Blockly.JavaScript.valueToCode(block, 'SCHEDULE', Blockly.JavaScript.ORDER_ATOMIC);
936
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
937
-
938
- return `${fName} = schedule(${vSchedule}, async () => {\n` +
939
- statement +
940
- '});\n';
941
- };
942
-
943
- // --- clearSchedule -----------------------------------------------------------
944
- Blockly.Trigger.getAllSchedules = function (workspace) {
945
- const blocks = workspace.getAllBlocks();
946
- const result = [];
947
-
948
- // Iterate through every block and check the name.
949
- for (let i = 0; i < blocks.length; i++) {
950
- if (blocks[i].isSchedule_) {
951
- result.push([blocks[i].getFieldValue('NAME'), blocks[i].getFieldValue('NAME')]);
952
- }
953
- }
954
-
955
- // BF(2020.05.16): for back compatibility. Remove it after 5 years
956
- if (window.scripts.loading) {
957
- const variables = workspace.getVariablesOfType('');
958
- variables.forEach(v => !result.find(it => it[0] === v.name) && result.push([v.name, v.name]));
959
- }
960
-
961
- const variables1 = workspace.getVariablesOfType('cron');
962
- variables1.forEach(v => !result.find(it => it[0] === v.name) && result.push([v.name, v.name]));
963
-
964
- !result.length && result.push(['', '']);
965
-
966
- return result;
967
- };
968
-
969
- Blockly.Trigger.blocks['schedule_clear'] =
970
- '<sep gap="5"></sep>' +
971
- '<block type="schedule_clear">' +
972
- ' <field name="NAME"></field>' +
973
- '</block>';
974
-
975
- Blockly.Blocks['schedule_clear'] = {
976
- init: function () {
977
- this.appendDummyInput('NAME')
978
- .appendField(Blockly.Translate('schedule_clear'))
979
- .appendField(new Blockly.FieldDropdown(function () {
980
- return scripts.blocklyWorkspace ? Blockly.Trigger.getAllSchedules(scripts.blocklyWorkspace) : [];
981
- }), 'NAME');
982
-
983
- this.setInputsInline(true);
984
- this.setPreviousStatement(true, null);
985
- this.setNextStatement(true, null);
986
-
987
- this.setColour(Blockly.Trigger.HUE);
988
-
989
- this.setTooltip(Blockly.Translate('schedule_clear_tooltip'));
990
- this.setHelpUrl(getHelp('schedule_clear_help'));
991
- },
992
- };
993
-
994
- Blockly.JavaScript.forBlock['schedule_clear'] = function (block) {
995
- const fName = Blockly.JavaScript.nameDB_.safeName(block.getFieldValue('NAME'));
996
-
997
- return `(() => { if (${fName}) { clearSchedule(${fName}); ${fName} = null; }})();\n`;
998
- };
999
-
1000
- // --- CRON dialog --------------------------------------------------
1001
- Blockly.Trigger.blocks['field_cron'] =
1002
- '<sep gap="5"></sep>' +
1003
- '<block type="field_cron">' +
1004
- ' <field name="CRON">* * * * *</field>' +
1005
- '</block>';
1006
-
1007
- Blockly.Blocks['field_cron'] = {
1008
- // Checkbox.
1009
- init: function () {
1010
- this.appendDummyInput()
1011
- .appendField(Blockly.Translate('field_cron_CRON'));
1012
-
1013
- this.appendDummyInput()
1014
- .appendField(new Blockly.FieldCRON('* * * * *'), 'CRON');
1015
-
1016
- this.setInputsInline(true);
1017
- this.setOutput(true, 'String');
1018
-
1019
- this.setColour(Blockly.Trigger.HUE);
1020
-
1021
- this.setTooltip(Blockly.Translate('field_cron_tooltip'));
1022
- },
1023
- };
1024
-
1025
- Blockly.JavaScript.forBlock['field_cron'] = function (block) {
1026
- const fCron = block.getFieldValue('CRON');
1027
-
1028
- return [`'${fCron}'`, Blockly.JavaScript.ORDER_ATOMIC];
1029
- };
1030
-
1031
- // --- CRON builder --------------------------------------------------
1032
- Blockly.Trigger.blocks['cron_builder'] =
1033
- '<sep gap="5"></sep>' +
1034
- '<block type="cron_builder">' +
1035
- ' <mutation seconds="false" as_line="false"></mutation>' +
1036
- ' <field name="LINE">FALSE</field>' +
1037
- ' <field name="WITH_SECONDS">FALSE</field>' +
1038
- ' <value name="DOW">' +
1039
- ' <shadow type="text">' +
1040
- ' <field name="TEXT">*</field>' +
1041
- ' </shadow>' +
1042
- ' </value>' +
1043
- ' <value name="MONTHS">' +
1044
- ' <shadow type="text">' +
1045
- ' <field name="TEXT">*</field>' +
1046
- ' </shadow>' +
1047
- ' </value>' +
1048
- ' <value name="DAYS">' +
1049
- ' <shadow type="text">' +
1050
- ' <field name="TEXT">*</field>' +
1051
- ' </shadow>' +
1052
- ' </value>' +
1053
- ' <value name="HOURS">' +
1054
- ' <shadow type="text">' +
1055
- ' <field name="TEXT">*</field>' +
1056
- ' </shadow>' +
1057
- ' </value>' +
1058
- ' <value name="MINUTES">' +
1059
- ' <shadow type="text">' +
1060
- ' <field name="TEXT">*</field>' +
1061
- ' </shadow>' +
1062
- ' </value>' +
1063
- '</block>';
1064
-
1065
- Blockly.Blocks['cron_builder'] = {
1066
- // Checkbox.
1067
- init: function () {
1068
- this.appendDummyInput()
1069
- .appendField(Blockly.Translate('cron_builder_CRON'));
1070
-
1071
- this.appendDummyInput('LINE')
1072
- .appendField(Blockly.Translate('cron_builder_line'))
1073
- .appendField(new Blockly.FieldCheckbox('FALSE', function (option) {
1074
- this.sourceBlock_.setInputsInline(option === true || option === 'true' || option === 'TRUE');
1075
- }), 'LINE');
1076
-
1077
- let _input = this.appendValueInput('DOW')
1078
- .appendField(Blockly.Translate('cron_builder_dow'));
1079
-
1080
- const wp = this.workspace;
1081
-
1082
- setTimeout(__input => {
1083
- if (!__input.connection.isConnected()) {
1084
- const _shadow = wp.newBlock('text');
1085
- _shadow.setShadow(true);
1086
- _shadow.setFieldValue('*', 'TEXT');
1087
- _shadow.outputConnection.connect(__input.connection);
1088
- }
1089
- }, 100, _input);
1090
-
1091
- _input = this.appendValueInput('MONTHS')
1092
- .appendField(Blockly.Translate('cron_builder_month'));
1093
-
1094
- setTimeout(__input => {
1095
- if (!__input.connection.isConnected()) {
1096
- const _shadow = wp.newBlock('text');
1097
- _shadow.setShadow(true);
1098
- _shadow.setFieldValue('*', 'TEXT');
1099
- _shadow.outputConnection.connect(__input.connection);
1100
- }
1101
- }, 100, _input);
1102
-
1103
- _input = this.appendValueInput('DAYS')
1104
- .appendField(Blockly.Translate('cron_builder_day'));
1105
-
1106
- setTimeout(__input => {
1107
- if (!__input.connection.isConnected()) {
1108
- const _shadow = wp.newBlock('text');
1109
- _shadow.setShadow(true);
1110
- _shadow.setFieldValue('*', 'TEXT');
1111
- _shadow.outputConnection.connect(__input.connection);
1112
- }
1113
- }, 100, _input);
1114
-
1115
- _input = this.appendValueInput('HOURS')
1116
- .appendField(Blockly.Translate('cron_builder_hour'));
1117
-
1118
- setTimeout(__input => {
1119
- if (!__input.connection.isConnected()) {
1120
- const _shadow = wp.newBlock('text');
1121
- _shadow.setShadow(true);
1122
- _shadow.setFieldValue('*', 'TEXT');
1123
- _shadow.outputConnection.connect(__input.connection);
1124
- }
1125
- }, 100, _input);
1126
-
1127
- _input = this.appendValueInput('MINUTES')
1128
- .appendField(Blockly.Translate('cron_builder_minutes'));
1129
-
1130
- setTimeout(__input => {
1131
- if (!__input.connection.isConnected()) {
1132
- const _shadow = wp.newBlock('text');
1133
- _shadow.setShadow(true);
1134
- _shadow.setFieldValue('*', 'TEXT');
1135
- _shadow.outputConnection.connect(__input.connection);
1136
- }
1137
- }, 100, _input);
1138
-
1139
- this.appendDummyInput('WITH_SECONDS')
1140
- .appendField(Blockly.Translate('cron_builder_with_seconds'))
1141
- .appendField(new Blockly.FieldCheckbox('FALSE', function (option) {
1142
- const withSeconds = option === true || option === 'true' || option === 'TRUE';
1143
- this.sourceBlock_.updateShape_(withSeconds);
1144
- }), 'WITH_SECONDS');
1145
-
1146
- this.seconds_ = false;
1147
- this.as_line_ = false;
1148
-
1149
- this.setInputsInline(this.as_line_);
1150
- this.setOutput(true, 'String');
1151
-
1152
- this.setColour(Blockly.Trigger.HUE);
1153
-
1154
- this.setTooltip(Blockly.Translate('field_cron_tooltip'));
1155
- },
1156
- /**
1157
- * Create XML to represent the number of text inputs.
1158
- * @return {!Element} XML storage element.
1159
- * @this Blockly.Block
1160
- */
1161
- mutationToDom: function () {
1162
- const container = document.createElement('mutation');
1163
- container.setAttribute('seconds', this.seconds_);
1164
- container.setAttribute('as_line', this.as_line_);
1165
-
1166
- return container;
1167
- },
1168
- /**
1169
- * Parse XML to restore the text inputs.
1170
- * @param {!Element} xmlElement XML storage element.
1171
- * @this Blockly.Block
1172
- */
1173
- domToMutation: function (xmlElement) {
1174
- this.seconds_ = xmlElement.getAttribute('seconds') === 'true';
1175
- this.as_line_ = xmlElement.getAttribute('as_line') === 'true';
1176
-
1177
- this.setInputsInline(this.as_line_);
1178
- this.updateShape_(this.seconds_);
1179
- },
1180
- updateShape_: function (withSeconds) {
1181
- this.seconds_ = withSeconds;
1182
- // Add or remove a statement Input.
1183
- let inputExists;
1184
- try {
1185
- inputExists = this.getInput('SECONDS');
1186
- } catch (e) {
1187
- inputExists = null;
1188
- }
1189
-
1190
- if (withSeconds) {
1191
- if (!inputExists) {
1192
- const _input = this.appendValueInput('SECONDS');
1193
- _input.appendField(Blockly.Translate('cron_builder_seconds'));
1194
- const wp = this.workspace;
1195
- setTimeout(__input => {
1196
- if (!__input.connection.isConnected()) {
1197
- const _shadow = wp.newBlock('text');
1198
- _shadow.setShadow(true);
1199
- _shadow.setFieldValue('*', 'TEXT');
1200
- _shadow.initSvg();
1201
- _shadow.render();
1202
- _shadow.outputConnection.connect(__input.connection);
1203
- }
1204
- }, 100, _input);
1205
- }
1206
- } else if (inputExists) {
1207
- this.removeInput('SECONDS');
1208
- }
1209
- },
1210
- };
1211
-
1212
- Blockly.JavaScript.forBlock['cron_builder'] = function (block) {
1213
- const vDow = Blockly.JavaScript.valueToCode(block, 'DOW', Blockly.JavaScript.ORDER_ATOMIC);
1214
- const vMonths = Blockly.JavaScript.valueToCode(block, 'MONTHS', Blockly.JavaScript.ORDER_ATOMIC);
1215
- const vDays = Blockly.JavaScript.valueToCode(block, 'DAYS', Blockly.JavaScript.ORDER_ATOMIC);
1216
- const vHours = Blockly.JavaScript.valueToCode(block, 'HOURS', Blockly.JavaScript.ORDER_ATOMIC);
1217
- const vMinutes = Blockly.JavaScript.valueToCode(block, 'MINUTES', Blockly.JavaScript.ORDER_ATOMIC);
1218
- const fWithSeconds = block.getFieldValue('WITH_SECONDS');
1219
- let vSeconds = '0';
1220
- if (fWithSeconds) {
1221
- try {
1222
- vSeconds = Blockly.JavaScript.valueToCode(block, 'SECONDS', Blockly.JavaScript.ORDER_ATOMIC);
1223
- } catch (e) {
1224
- // If no seconds input exists, we set it to an empty string
1225
- }
1226
- }
1227
-
1228
- const code =
1229
- (fWithSeconds === 'TRUE' || fWithSeconds === 'true' || fWithSeconds === true ?
1230
- vSeconds + `.toString().trim() + ' ' + ` : '') +
1231
- vMinutes + `.toString().trim() + ' ' + ` +
1232
- vHours + `.toString().trim() + ' ' + ` +
1233
- vDays + `.toString().trim() + ' ' + ` +
1234
- vMonths + `.toString().trim() + ' ' + ` +
1235
- vDow + '.toString().trim()';
1236
-
1237
- return [code, Blockly.JavaScript.ORDER_ATOMIC];
1238
- };
1239
-
1240
- // --- onMessage -----------------------------------------------------------
1241
- Blockly.Trigger.blocks['onMessage'] =
1242
- '<block type="onMessage">' +
1243
- ' <field name="MESSAGE">customMessage</field>' +
1244
- '</block>';
1245
-
1246
- Blockly.Blocks['onMessage'] = {
1247
- init: function () {
1248
- this.appendDummyInput('NAME')
1249
- .appendField('✉️ ' + Blockly.Translate('onMessage'));
1250
-
1251
- this.appendDummyInput('MESSAGE')
1252
- .appendField(Blockly.Translate('onMessage_message'))
1253
- .appendField(new Blockly.FieldTextInput('customMessage'), 'MESSAGE');
1254
-
1255
- this.appendStatementInput('STATEMENT')
1256
- .setCheck(null);
1257
-
1258
- this.setInputsInline(false);
1259
- this.setPreviousStatement(true, null);
1260
- this.setNextStatement(true, null);
1261
-
1262
- this.setColour(Blockly.Trigger.HUE);
1263
-
1264
- this.setTooltip(Blockly.Translate('onMessage_tooltip'));
1265
- this.setHelpUrl(getHelp('onMessage_help'));
1266
- },
1267
- /**
1268
- * Called whenever anything on the workspace changes.
1269
- * Add warning if this flow block is not nested inside a loop.
1270
- * @param {!Blockly.Events.Abstract} e Change event.
1271
- * @this Blockly.Block
1272
- */
1273
- onchange: function (e) {
1274
- let legal = true;
1275
-
1276
- // Is the block nested in a trigger?
1277
- let block = this;
1278
- while (block = block.getSurroundParent()) {
1279
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
1280
- legal = false;
1281
- break;
1282
- }
1283
- }
1284
-
1285
- if (legal) {
1286
- this.setWarningText(null, this.id);
1287
- } else {
1288
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
1289
- }
1290
- },
1291
- };
1292
-
1293
- Blockly.JavaScript.forBlock['onMessage'] = function (block) {
1294
- const fMessage = block.getFieldValue('MESSAGE');
1295
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
1296
-
1297
- return `onMessage(${Blockly.JavaScript.quote_(fMessage)}, async (data, callback) => {\n` +
1298
- statement +
1299
- Blockly.JavaScript.prefixLines(`typeof callback === 'function' && callback({ result: true }); // default callback`, Blockly.JavaScript.INDENT) + '\n' +
1300
- '});\n';
1301
- };
1302
-
1303
- // --- onMessage_data -----------------------------------------------------------
1304
- Blockly.Trigger.blocks['onMessage_data'] =
1305
- '<sep gap="5"></sep>' +
1306
- '<block type="onMessage_data">' +
1307
- ' <field name="ATTR">data</field>' +
1308
- '</block>';
1309
-
1310
- Blockly.Blocks['onMessage_data'] = {
1311
- /**
1312
- * Block for conditionally returning a value from a procedure.
1313
- * @this Blockly.Block
1314
- */
1315
- init: function () {
1316
- this.appendDummyInput()
1317
- .appendField('✉️ ');
1318
-
1319
- this.appendDummyInput('ATTR')
1320
- .appendField(new Blockly.FieldDropdown([
1321
- [Blockly.Translate('onMessage_data_data'), 'data'],
1322
- ]), 'ATTR');
1323
-
1324
- this.setInputsInline(true);
1325
- this.setOutput(true);
1326
-
1327
- this.setColour(Blockly.Action.HUE);
1328
-
1329
- this.setTooltip(Blockly.Translate('onMessage_data_tooltip'));
1330
- this.setHelpUrl(getHelp('onMessage_data_help'));
1331
- },
1332
- /**
1333
- * Called whenever anything on the workspace changes.
1334
- * Add warning if this flow block is not nested inside a loop.
1335
- * @param {!Blockly.Events.Abstract} e Change event.
1336
- * @this Blockly.Block
1337
- */
1338
- onchange: function (e) {
1339
- let legal = false;
1340
- // Is the block nested in a trigger?
1341
- let block = this;
1342
- do {
1343
- if (this.FUNCTION_TYPES.includes(block.type)) {
1344
- legal = true;
1345
- break;
1346
- }
1347
- block = block.getSurroundParent();
1348
- } while (block);
1349
-
1350
- if (legal) {
1351
- this.setWarningText(null, this.id);
1352
- } else {
1353
- this.setWarningText(Blockly.Translate('onMessage_data_warning'), this.id);
1354
- }
1355
- },
1356
- /**
1357
- * List of block types that are functions and thus do not need warnings.
1358
- * To add a new function type add this to your code:
1359
- * Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
1360
- */
1361
- FUNCTION_TYPES: ['onMessage'],
1362
- };
1363
- Blockly.JavaScript.forBlock['onMessage_data'] = function (block) {
1364
- const fAttr = block.getFieldValue('ATTR');
1365
-
1366
- return [fAttr, Blockly.JavaScript.ORDER_ATOMIC];
1367
- };
1368
-
1369
- // --- onFile -----------------------------------------------------------
1370
- Blockly.Trigger.blocks['onFile'] =
1371
- '<block type="onFile">' +
1372
- ' <field name="WITH_FILE">FALSE</field>' +
1373
- ' <value name="OID">' +
1374
- ' <shadow type="field_oid_meta">' +
1375
- ' <field name="oid">0_userdata.0</field>' +
1376
- ' </shadow>' +
1377
- ' </value>' +
1378
- ' <value name="FILE">' +
1379
- ' <shadow type="text">' +
1380
- ' <field name="TEXT">*</field>' +
1381
- ' </shadow>' +
1382
- ' </value>' +
1383
- '</block>';
1384
-
1385
- Blockly.Blocks['onFile'] = {
1386
- init: function () {
1387
- this.appendValueInput('OID')
1388
- .appendField('📁 ' + Blockly.Translate('onFile'))
1389
- .setCheck(null);
1390
-
1391
- this.appendValueInput('FILE')
1392
- .appendField(Blockly.Translate('onFile_file'))
1393
- .setCheck(null);
1394
-
1395
- this.appendDummyInput('WITH_FILE_INPUT')
1396
- .appendField(Blockly.Translate('onFile_withFile'))
1397
- .appendField(new Blockly.FieldCheckbox('FALSE'), 'WITH_FILE');
1398
-
1399
- this.appendStatementInput('STATEMENT')
1400
- .setCheck(null);
1401
-
1402
- this.setInputsInline(false);
1403
- this.setPreviousStatement(true, null);
1404
- this.setNextStatement(true, null);
1405
-
1406
- this.setColour(Blockly.Trigger.HUE);
1407
-
1408
- this.setTooltip(Blockly.Translate('onFile_tooltip'));
1409
- this.setHelpUrl(getHelp('onFile_help'));
1410
- },
1411
- /**
1412
- * Called whenever anything on the workspace changes.
1413
- * Add warning if this flow block is not nested inside a loop.
1414
- * @param {!Blockly.Events.Abstract} e Change event.
1415
- * @this Blockly.Block
1416
- */
1417
- onchange: function (e) {
1418
- let legal = true;
1419
-
1420
- // Is the block nested in a trigger?
1421
- let block = this;
1422
- while (block = block.getSurroundParent()) {
1423
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
1424
- legal = false;
1425
- break;
1426
- }
1427
- }
1428
-
1429
- if (legal) {
1430
- this.setWarningText(null, this.id);
1431
- } else {
1432
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
1433
- }
1434
- },
1435
- };
1436
-
1437
- Blockly.JavaScript.forBlock['onFile'] = function (block) {
1438
- const vObjId = Blockly.JavaScript.valueToCode(block, 'OID', Blockly.JavaScript.ORDER_ATOMIC);
1439
- const vFile = Blockly.JavaScript.valueToCode(block, 'FILE', Blockly.JavaScript.ORDER_ATOMIC);
1440
- const fWithFile = block.getFieldValue('WITH_FILE');
1441
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
1442
-
1443
- let objectName = '';
1444
- try {
1445
- const objId = eval(vObjId); // Code to string
1446
- objectName = main.objects[objId] && main.objects[objId].common && main.objects[objId].common.name ? main.objects[objId].common.name : '';
1447
- if (typeof objectName === 'object') {
1448
- objectName = objectName[systemLang] || objectName.en;
1449
- }
1450
- } catch (error) {
1451
-
1452
- }
1453
-
1454
- return `onFile(${vObjId}${objectName ? ` /* ${objectName} */` : ''}, ${vFile}, ${fWithFile === 'TRUE' ? 'true' : 'false'}, ` +
1455
- 'async (id, fileName, size, data, mimeType) => {\n' +
1456
- statement +
1457
- '});\n';
1458
- };
1459
-
1460
- // --- onFile_data -----------------------------------------------------------
1461
- Blockly.Trigger.blocks['onFile_data'] =
1462
- '<sep gap="5"></sep>' +
1463
- '<block type="onFile_data">' +
1464
- ' <field name="ATTR">data</field>' +
1465
- '</block>';
1466
-
1467
- Blockly.Blocks['onFile_data'] = {
1468
- /**
1469
- * Block for conditionally returning a value from a procedure.
1470
- * @this Blockly.Block
1471
- */
1472
- init: function () {
1473
- this.appendDummyInput()
1474
- .appendField('📁');
1475
-
1476
- this.appendDummyInput('ATTR')
1477
- .appendField(new Blockly.FieldDropdown([
1478
- [Blockly.Translate('onFile_data_data'), 'data'],
1479
- [Blockly.Translate('onFile_data_filename'), 'fileName'],
1480
- [Blockly.Translate('onFile_data_size'), 'size'],
1481
- [Blockly.Translate('onFile_data_mimeType'), 'mimeType'],
1482
- [Blockly.Translate('onFile_data_id'), 'id'],
1483
- [Blockly.Translate('onFile_data_tempFile'), 'TEMP_FILE_PATH'],
1484
- ]), 'ATTR');
1485
-
1486
- this.setInputsInline(true);
1487
- this.setOutput(true);
1488
-
1489
- this.setColour(Blockly.Trigger.HUE);
1490
-
1491
- this.setTooltip(Blockly.Translate('onFile_data_tooltip'));
1492
- //this.setHelpUrl(getHelp('onFile_data'));
1493
- },
1494
- /**
1495
- * Called whenever anything on the workspace changes.
1496
- * Add warning if this flow block is not nested inside a loop.
1497
- * @param {!Blockly.Events.Abstract} e Change event.
1498
- * @this Blockly.Block
1499
- */
1500
- onchange: function (e) {
1501
- let legal = false;
1502
- // Is the block nested in a trigger?
1503
- let block = this;
1504
- do {
1505
- if (this.FUNCTION_TYPES.includes(block.type)) {
1506
- legal = true;
1507
- break;
1508
- }
1509
- block = block.getSurroundParent();
1510
- } while (block);
1511
-
1512
- if (legal) {
1513
- this.setWarningText(null, this.id);
1514
- } else {
1515
- this.setWarningText(Blockly.Translate('onFile_data_warning'), this.id);
1516
- }
1517
- },
1518
- /**
1519
- * List of block types that are functions and thus do not need warnings.
1520
- * To add a new function type add this to your code:
1521
- * Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
1522
- */
1523
- FUNCTION_TYPES: ['onFile'],
1524
- };
1525
- Blockly.JavaScript.forBlock['onFile_data'] = function (block) {
1526
- const fAttr = block.getFieldValue('ATTR');
1527
-
1528
- if (fAttr === 'TEMP_FILE_PATH') {
1529
- return [`createTempFile(fileName, data)`, Blockly.JavaScript.ORDER_ATOMIC];
1530
- } else {
1531
- return [fAttr, Blockly.JavaScript.ORDER_ATOMIC];
1532
- }
1533
- };
1534
-
1535
- // --- onFile -----------------------------------------------------------
1536
- Blockly.Trigger.blocks['offFile'] =
1537
- '<sep gap="5"></sep>' +
1538
- '<block type="offFile">' +
1539
- ' <value name="OID">' +
1540
- ' <shadow type="field_oid_meta">' +
1541
- ' <field name="oid">0_userdata.0</field>' +
1542
- ' </shadow>' +
1543
- ' </value>' +
1544
- ' <value name="FILE">' +
1545
- ' <shadow type="text">' +
1546
- ' <field name="TEXT">*</field>' +
1547
- ' </shadow>' +
1548
- ' </value>' +
1549
- '</block>';
1550
-
1551
- Blockly.Blocks['offFile'] = {
1552
- init: function () {
1553
- this.appendValueInput('OID')
1554
- .appendField('📁 ' + Blockly.Translate('offFile'))
1555
- .setCheck(null);
1556
-
1557
- this.appendValueInput('FILE')
1558
- .appendField(Blockly.Translate('onFile_file'))
1559
- .setCheck(null);
1560
-
1561
- this.setInputsInline(false);
1562
- this.setPreviousStatement(true, null);
1563
- this.setNextStatement(true, null);
1564
-
1565
- this.setColour(Blockly.Trigger.HUE);
1566
-
1567
- this.setTooltip(Blockly.Translate('offFile_tooltip'));
1568
- this.setHelpUrl(getHelp('offFile_help'));
1569
- },
1570
- };
1571
-
1572
- Blockly.JavaScript.forBlock['offFile'] = function (block) {
1573
- const vObjId = Blockly.JavaScript.valueToCode(block, 'OID', Blockly.JavaScript.ORDER_ATOMIC);
1574
- const vFile = Blockly.JavaScript.valueToCode(block, 'FILE', Blockly.JavaScript.ORDER_ATOMIC);
1575
-
1576
- let objectName = '';
1577
- try {
1578
- const objId = eval(vObjId); // Code to string
1579
- objectName = main.objects[objId] && main.objects[objId].common && main.objects[objId].common.name ? main.objects[objId].common.name : '';
1580
- if (typeof objectName === 'object') {
1581
- objectName = objectName[systemLang] || objectName.en;
1582
- }
1583
- } catch (error) {
1584
-
1585
- }
1586
-
1587
- return `offFile(${vObjId}${objectName ? ` /* ${objectName} */` : ''}, ${vFile});\n`;
1588
- };
1589
-
1590
- // --- onLog -----------------------------------------------------------
1591
- Blockly.Trigger.blocks['onLog'] =
1592
- '<block type="onLog">' +
1593
- ' <field name="Severity">error</field>' +
1594
- '</block>';
1595
-
1596
- Blockly.Blocks['onLog'] = {
1597
- init: function () {
1598
- this.appendDummyInput('TEXT')
1599
- .appendField('💬 ' + Blockly.Translate('onLog'));
1600
-
1601
- this.appendDummyInput('Severity')
1602
- .appendField(Blockly.Translate('loglevel'))
1603
- .appendField(new Blockly.FieldDropdown([
1604
- [Blockly.Translate('loglevel_error'), 'error'],
1605
- [Blockly.Translate('loglevel_warn'), 'warn'],
1606
- [Blockly.Translate('loglevel_info'), 'info'],
1607
- [Blockly.Translate('loglevel_debug'), 'debug'],
1608
- [Blockly.Translate('loglevel_all'), '*'],
1609
- ]), 'Severity');
1610
-
1611
- this.appendStatementInput('STATEMENT')
1612
- .setCheck(null);
1613
-
1614
- this.setInputsInline(false);
1615
- this.setPreviousStatement(true, null);
1616
- this.setNextStatement(true, null);
1617
-
1618
- this.setColour(Blockly.Trigger.HUE);
1619
-
1620
- this.setTooltip(Blockly.Translate('onLog_tooltip'));
1621
- this.setHelpUrl(getHelp('onLog_help'));
1622
- },
1623
- /**
1624
- * Called whenever anything on the workspace changes.
1625
- * Add warning if this flow block is not nested inside a loop.
1626
- * @param {!Blockly.Events.Abstract} e Change event.
1627
- * @this Blockly.Block
1628
- */
1629
- onchange: function (e) {
1630
- let legal = true;
1631
-
1632
- // Is the block nested in a trigger?
1633
- let block = this;
1634
- while (block = block.getSurroundParent()) {
1635
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
1636
- legal = false;
1637
- break;
1638
- }
1639
- }
1640
-
1641
- if (legal) {
1642
- this.setWarningText(null, this.id);
1643
- } else {
1644
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
1645
- }
1646
- },
1647
- };
1648
-
1649
- Blockly.JavaScript.forBlock['onLog'] = function (block) {
1650
- const fSeverity = block.getFieldValue('Severity');
1651
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
1652
-
1653
- return `onLog('${fSeverity}', async (data) => {\n` +
1654
- statement +
1655
- '});\n';
1656
- };
1657
-
1658
- // --- onLog_data -----------------------------------------------------------
1659
- Blockly.Trigger.blocks['onLog_data'] =
1660
- '<sep gap="5"></sep>' +
1661
- '<block type="onLog_data">' +
1662
- ' <field name="ATTR">data.message</field>' +
1663
- '</block>';
1664
-
1665
- Blockly.Blocks['onLog_data'] = {
1666
- /**
1667
- * Block for conditionally returning a value from a procedure.
1668
- * @this Blockly.Block
1669
- */
1670
- init: function () {
1671
- this.appendDummyInput()
1672
- .appendField('💬 ');
1673
-
1674
- this.appendDummyInput('ATTR')
1675
- .appendField(new Blockly.FieldDropdown([
1676
- [Blockly.Translate('onLog_data_message'), 'data.message'],
1677
- [Blockly.Translate('loglevel'), 'data.severity'],
1678
- [Blockly.Translate('onLog_data_from'), 'data.from'],
1679
- [Blockly.Translate('onLog_data_ts'), 'data.ts'],
1680
- ]), 'ATTR');
1681
-
1682
- this.setInputsInline(true);
1683
- this.setOutput(true);
1684
-
1685
- this.setColour(Blockly.Trigger.HUE);
1686
-
1687
- this.setTooltip(Blockly.Translate('onLog_data_tooltip'));
1688
- //this.setHelpUrl(getHelp('onLog_data_help'));
1689
- },
1690
- /**
1691
- * Called whenever anything on the workspace changes.
1692
- * Add warning if this flow block is not nested inside a loop.
1693
- * @param {!Blockly.Events.Abstract} e Change event.
1694
- * @this Blockly.Block
1695
- */
1696
- onchange: function (e) {
1697
- let legal = false;
1698
- // Is the block nested in a trigger?
1699
- let block = this;
1700
- do {
1701
- if (this.FUNCTION_TYPES.includes(block.type)) {
1702
- legal = true;
1703
- break;
1704
- }
1705
- block = block.getSurroundParent();
1706
- } while (block);
1707
-
1708
- if (legal) {
1709
- this.setWarningText(null, this.id);
1710
- } else {
1711
- this.setWarningText(Blockly.Translate('onLog_data_warning'), this.id);
1712
- }
1713
- },
1714
- /**
1715
- * List of block types that are functions and thus do not need warnings.
1716
- * To add a new function type add this to your code:
1717
- * Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
1718
- */
1719
- FUNCTION_TYPES: ['onLog'],
1720
- };
1721
- Blockly.JavaScript.forBlock['onLog_data'] = function (block) {
1722
- const fAttr = block.getFieldValue('ATTR');
1723
-
1724
- return [fAttr, Blockly.JavaScript.ORDER_ATOMIC];
1725
- };
1726
-
1727
- // --- onEnumMembers -----------------------------------------------------------
1728
- Blockly.Trigger.blocks['onEnumMembers'] =
1729
- '<block type="onEnumMembers">' +
1730
- '</block>';
1731
-
1732
- Blockly.Blocks['onEnumMembers'] = {
1733
- init: function () {
1734
- this.appendDummyInput()
1735
- .appendField(Blockly.Translate('onEnumMembers'));
1736
-
1737
- this.appendDummyInput('OID')
1738
- .appendField(new Blockly.FieldOID(Blockly.Translate('select_id'), 'enum'), 'OID');
1739
-
1740
- this.appendStatementInput('STATEMENT')
1741
- .setCheck(null);
1742
-
1743
- this.setInputsInline(false);
1744
- this.setPreviousStatement(true, null);
1745
- this.setNextStatement(true, null);
1746
-
1747
- this.setColour(Blockly.Trigger.HUE);
1748
-
1749
- this.setTooltip(Blockly.Translate('onEnumMembers_tooltip'));
1750
- this.setHelpUrl(getHelp('onEnumMembers_help'));
1751
- },
1752
- /**
1753
- * Called whenever anything on the workspace changes.
1754
- * Add warning if this flow block is not nested inside a loop.
1755
- * @param {!Blockly.Events.Abstract} e Change event.
1756
- * @this Blockly.Block
1757
- */
1758
- onchange: function (e) {
1759
- let legal = true;
1760
-
1761
- // Is the block nested in a trigger?
1762
- let block = this;
1763
- while (block = block.getSurroundParent()) {
1764
- if (block && Blockly.Trigger.WARNING_PARENTS.includes(block.type)) {
1765
- legal = false;
1766
- break;
1767
- }
1768
- }
1769
-
1770
- if (legal) {
1771
- this.setWarningText(null, this.id);
1772
- } else {
1773
- this.setWarningText(Blockly.Translate('trigger_in_trigger_warning'), this.id);
1774
- }
1775
- },
1776
- };
1777
- Blockly.JavaScript.forBlock['onEnumMembers'] = function (block) {
1778
- const fObjId = block.getFieldValue('OID');
1779
- const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
1780
-
1781
- let objectName = main.objects[fObjId] && main.objects[fObjId].common && main.objects[fObjId].common.name ? main.objects[fObjId].common.name : '';
1782
- if (typeof objectName === 'object') {
1783
- objectName = objectName[systemLang] || objectName.en;
1784
- }
1785
-
1786
- return `onEnumMembers('${fObjId}'${objectName ? ` /* ${objectName} */` : ''}, async (obj) => {\n` +
1787
- Blockly.JavaScript.prefixLines('let value = obj.state.val;', Blockly.JavaScript.INDENT) + '\n' +
1788
- Blockly.JavaScript.prefixLines('let oldValue = obj.oldState.val;', Blockly.JavaScript.INDENT) + '\n' +
1789
- statement +
1790
- '});\n';
1791
- };