Skip to content

Commit

Permalink
chore: release v7.11.0
Browse files Browse the repository at this point in the history
* (klein0r) Added blockly block for read and write file
* (klein0r) Allow to select other object types than state in some blocks
* (klein0r) Improved translations
* (klein0r) Removed 'type' from dropdown (is always 'state')
* (klein0r) Use highlight in search (instead of select)
* (klein0r) Added option for httpGet to receive arraybuffer (download files)
  • Loading branch information
klein0r committed Mar 26, 2024
1 parent 7e6096a commit 3b10f93
Show file tree
Hide file tree
Showing 18 changed files with 402 additions and 79 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG_OLD.md
@@ -1,4 +1,9 @@
The newest change log is in README.md
## 7.9.3 (2024-03-19)

* (klein0r) Added timeout option for http blocks
* (klein0r) Added option for basic auth in url (user:pass)

## 7.9.2 (2024-03-18)

* (klein0r) Added new block for http response
Expand Down
7 changes: 1 addition & 6 deletions README.md
Expand Up @@ -42,7 +42,7 @@ Since v5.5.0 of the JavaScript adapter the following locations (relative to the
<!--
### **WORK IN PROGRESS**
-->
### **WORK IN PROGRESS**
### 7.11.0 (2024-03-26)

* (klein0r) Added blockly block for read and write file
* (klein0r) Allow to select other object types than state in some blocks
Expand Down Expand Up @@ -72,11 +72,6 @@ Since v5.5.0 of the JavaScript adapter the following locations (relative to the
* (klein0r) Fixed urlencoding for basic auth in url (user:pass)
* (klein0r) Added warning icon if trigger is positioned inside of another trigger or loop

### 7.9.3 (2024-03-19)

* (klein0r) Added timeout option for http blocks
* (klein0r) Added option for basic auth in url (user:pass)

## License
The MIT License (MIT)

Expand Down
10 changes: 5 additions & 5 deletions admin/asset-manifest.json
@@ -1,8 +1,8 @@
{
"files": {
"main.js": "/static/js/main.4e0a684a.js",
"main.js": "/static/js/main.01873cd9.js",
"static/css/864.42bfc5f3.chunk.css": "/static/css/864.42bfc5f3.chunk.css",
"static/js/864.4f070a1f.chunk.js": "/static/js/864.4f070a1f.chunk.js",
"static/js/864.2e977ad1.chunk.js": "/static/js/864.2e977ad1.chunk.js",
"static/js/805.7c367e53.chunk.js": "/static/js/805.7c367e53.chunk.js",
"static/js/431.a62490cf.chunk.js": "/static/js/431.a62490cf.chunk.js",
"static/js/702.1692c400.chunk.js": "/static/js/702.1692c400.chunk.js",
Expand Down Expand Up @@ -160,9 +160,9 @@
"static/media/Garage Doors.svg": "/static/media/Garage Doors.0c2a1cfca7ad1ea59625.svg",
"static/media/Outdoor Blinds.svg": "/static/media/Outdoor Blinds.37b85a9c060a4af48da9.svg",
"static/media/Upstairs.svg": "/static/media/Upstairs.441813e54e0daca0882d.svg",
"main.4e0a684a.js.map": "/static/js/main.4e0a684a.js.map",
"main.01873cd9.js.map": "/static/js/main.01873cd9.js.map",
"864.42bfc5f3.chunk.css.map": "/static/css/864.42bfc5f3.chunk.css.map",
"864.4f070a1f.chunk.js.map": "/static/js/864.4f070a1f.chunk.js.map",
"864.2e977ad1.chunk.js.map": "/static/js/864.2e977ad1.chunk.js.map",
"805.7c367e53.chunk.js.map": "/static/js/805.7c367e53.chunk.js.map",
"431.a62490cf.chunk.js.map": "/static/js/431.a62490cf.chunk.js.map",
"702.1692c400.chunk.js.map": "/static/js/702.1692c400.chunk.js.map",
Expand Down Expand Up @@ -195,6 +195,6 @@
"96.fe9915d5.chunk.js.map": "/static/js/96.fe9915d5.chunk.js.map"
},
"entrypoints": [
"static/js/main.4e0a684a.js"
"static/js/main.01873cd9.js"
]
}
244 changes: 231 additions & 13 deletions admin/google-blockly/own/blocks_action.js
Expand Up @@ -128,23 +128,32 @@ Blockly.Action.blocks['http_get'] =
+ ' </value>'
+ ' <value name="UNIT">'
+ ' </value>'
+ ' <value name="TYPE">'
+ ' </value>'
+ ' <value name="STATEMENT">'
+ ' </value>'
+ '</block>';

Blockly.Blocks['http_get'] = {
init: function() {
this.appendValueInput('URL')
.appendField(Blockly.Translate('http_get'));
.appendField('🌐 ' + Blockly.Translate('http_get'));

this.appendDummyInput()
.appendField(Blockly.Translate('http_get_timeout'))
.appendField(Blockly.Translate('http_timeout'))
.appendField(new Blockly.FieldTextInput(2000), 'TIMEOUT')
.appendField(new Blockly.FieldDropdown([
[Blockly.Translate('http_get_settimeout_ms'), 'ms'],
[Blockly.Translate('http_get_settimeout_sec'), 'sec']
[Blockly.Translate('http_timeout_ms'), 'ms'],
[Blockly.Translate('http_timeout_sec'), 'sec']
]), 'UNIT');

this.appendDummyInput('TYPE')
.appendField(Blockly.Translate('http_type'))
.appendField(new Blockly.FieldDropdown([
[Blockly.Translate('http_type_text'), 'text'],
[Blockly.Translate('http_type_arraybuffer'), 'arraybuffer'],
]), 'TYPE');

this.appendStatementInput('STATEMENT')
.setCheck(null);

Expand All @@ -170,7 +179,12 @@ Blockly.JavaScript['http_get'] = function(block) {
timeout *= 1000;
}

return `httpGet(${URL}, { timeout: ${timeout} }, async (err, response) => {\n` +
let responseType = block.getFieldValue('TYPE');
if (!responseType) {
responseType = 'text';
}

return `httpGet(${URL}, { timeout: ${timeout}, responseType: '${responseType}' }, async (err, response) => {\n` +
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
Expand All @@ -190,6 +204,8 @@ Blockly.Action.blocks['http_post'] =
+ ' </value>'
+ ' <value name="UNIT">'
+ ' </value>'
+ ' <value name="TYPE">'
+ ' </value>'
+ ' <value name="DATA">'
+ ' <shadow type="object_new">'
+ ' </shadow>'
Expand All @@ -201,16 +217,23 @@ Blockly.Action.blocks['http_post'] =
Blockly.Blocks['http_post'] = {
init: function() {
this.appendValueInput('URL')
.appendField(Blockly.Translate('http_post'));
.appendField('🌐 ' + Blockly.Translate('http_post'));

this.appendDummyInput()
.appendField(Blockly.Translate('http_post_timeout'))
.appendField(Blockly.Translate('http_timeout'))
.appendField(new Blockly.FieldTextInput(2000), 'TIMEOUT')
.appendField(new Blockly.FieldDropdown([
[Blockly.Translate('http_post_settimeout_ms'), 'ms'],
[Blockly.Translate('http_post_settimeout_sec'), 'sec']
[Blockly.Translate('http_timeout_ms'), 'ms'],
[Blockly.Translate('http_timeout_sec'), 'sec']
]), 'UNIT');

this.appendDummyInput('TYPE')
.appendField(Blockly.Translate('http_type'))
.appendField(new Blockly.FieldDropdown([
[Blockly.Translate('http_type_text'), 'text'],
[Blockly.Translate('http_type_arraybuffer'), 'arraybuffer'],
]), 'TYPE');

this.appendValueInput('DATA')
.appendField(Blockly.Translate('http_post_data'));

Expand Down Expand Up @@ -240,19 +263,24 @@ Blockly.JavaScript['http_post'] = function(block) {
timeout *= 1000;
}

let responseType = block.getFieldValue('TYPE');
if (!responseType) {
responseType = 'text';
}

if (!data) {
data = 'null';
}

return `httpPost(${URL}, ${data}, { timeout: ${timeout} }, async (err, response) => {\n` +
return `httpPost(${URL}, ${data}, { timeout: ${timeout}, responseType: '${responseType}' }, async (err, response) => {\n` +
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
statement +
'});\n';
};

// --- get info about event -----------------------------------------------------------
// --- http_response -----------------------------------------------------------
Blockly.Action.blocks['http_response'] =
'<block type="http_response">'
+ ' <value name="ATTR">'
Expand All @@ -276,7 +304,7 @@ Blockly.Blocks['http_response'] = {

this.setInputsInline(true);
this.setOutput(true);
this.setColour(Blockly.Trigger.HUE);
this.setColour(Blockly.Action.HUE);
this.setTooltip(Blockly.Translate('http_response_tooltip'));
//this.setHelpUrl(getHelp('http_response'));
},
Expand Down Expand Up @@ -317,6 +345,196 @@ Blockly.JavaScript['http_response'] = function(block) {
return [attr, Blockly.JavaScript.ORDER_ATOMIC];
};

// --- action file_write --------------------------------------------------
Blockly.Action.blocks['file_write'] =
'<block type="file_write">'
+ ' <value name="OID">'
+ ' <shadow type="field_oid_meta">'
+ ' <field name="oid">0_userdata.0</field>'
+ ' </shadow>'
+ ' </value>'
+ ' <value name="FILE">'
+ ' <shadow type="text">'
+ ' <field name="TEXT">demo.json</field>'
+ ' </shadow>'
+ ' </value>'
+ ' <value name="DATA">'
+ ' </value>'
+ '</block>';

Blockly.Blocks['file_write'] = {
init: function() {
this.appendValueInput('OID')
.appendField('📁 ' + Blockly.Translate('file_write'));

this.appendValueInput('FILE')
.appendField(Blockly.Translate('file_write_filename'))
.setCheck(null);

this.appendValueInput('DATA')
.appendField(Blockly.Translate('file_write_data'));

this.setInputsInline(false);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);

this.setColour(Blockly.Action.HUE);
this.setTooltip(Blockly.Translate('file_write_tooltip'));
this.setHelpUrl(getHelp('file_write_help'));
}
};

Blockly.JavaScript['file_write'] = function(block) {
const value_objectid = Blockly.JavaScript.valueToCode(block, 'OID', Blockly.JavaScript.ORDER_ATOMIC);
const file = Blockly.JavaScript.valueToCode(block, 'FILE', Blockly.JavaScript.ORDER_ATOMIC);
const data = Blockly.JavaScript.valueToCode(block, 'DATA', Blockly.JavaScript.ORDER_ATOMIC);

let objectName = '';
try {
const objId = eval(value_objectid); // Code to string
objectName = main.objects[objId] && main.objects[objId].common && main.objects[objId].common.name ? main.objects[objId].common.name : '';
if (typeof objectName === 'object') {
objectName = objectName[systemLang] || objectName.en;
}
} catch (error) {

}

return `writeFile(${value_objectid}${objectName ? ` /* ${objectName} */` : ''}, String(${file}), ${data ? data : 'null'}, (err) => {\n` +
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
'});\n';
};

// --- action file_read --------------------------------------------------
Blockly.Action.blocks['file_read'] =
'<block type="file_read">'
+ ' <value name="OID">'
+ ' <shadow type="field_oid_meta">'
+ ' <field name="oid">0_userdata.0</field>'
+ ' </shadow>'
+ ' </value>'
+ ' <value name="FILE">'
+ ' <shadow type="text">'
+ ' <field name="TEXT">demo.json</field>'
+ ' </shadow>'
+ ' </value>'
+ ' <value name="STATEMENT">'
+ ' </value>'
+ '</block>';

Blockly.Blocks['file_read'] = {
init: function() {
this.appendValueInput('OID')
.appendField('📁 ' + Blockly.Translate('file_read'));

this.appendValueInput('FILE')
.appendField(Blockly.Translate('file_read_filename'))
.setCheck(null);

this.appendStatementInput('STATEMENT')
.setCheck(null);

this.setInputsInline(false);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);

this.setColour(Blockly.Action.HUE);
this.setTooltip(Blockly.Translate('file_read_tooltip'));
this.setHelpUrl(getHelp('file_read_help'));
}
};

Blockly.JavaScript['file_read'] = function(block) {
const value_objectid = Blockly.JavaScript.valueToCode(block, 'OID', Blockly.JavaScript.ORDER_ATOMIC);
const file = Blockly.JavaScript.valueToCode(block, 'FILE', Blockly.JavaScript.ORDER_ATOMIC);
const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');

let objectName = '';
try {
const objId = eval(value_objectid); // Code to string
objectName = main.objects[objId] && main.objects[objId].common && main.objects[objId].common.name ? main.objects[objId].common.name : '';
if (typeof objectName === 'object') {
objectName = objectName[systemLang] || objectName.en;
}
} catch (error) {

}

return `readFile(${value_objectid}${objectName ? ` /* ${objectName} */` : ''}, String(${file}), (err, data, mimeType) => {\n` +
Blockly.JavaScript.prefixLines(`if (err) {`, Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`console.error(err);`, Blockly.JavaScript.INDENT + Blockly.JavaScript.INDENT) + '\n' +
Blockly.JavaScript.prefixLines(`}`, Blockly.JavaScript.INDENT) + '\n' +
statement +
'});\n';
};

// --- file_data -----------------------------------------------------------
Blockly.Action.blocks['file_data'] =
'<block type="file_data">'
+ ' <value name="ATTR">'
+ ' </value>'
+ '</block>';

Blockly.Blocks['file_data'] = {
/**
* Block for conditionally returning a value from a procedure.
* @this Blockly.Block
*/
init: function() {
this.appendDummyInput()
.appendField('📁');

this.appendDummyInput('ATTR')
.appendField(new Blockly.FieldDropdown([
[Blockly.Translate('file_data_data'), 'data'],
[Blockly.Translate('file_data_mimeType'), 'mimeType'],
]), 'ATTR');

this.setInputsInline(true);
this.setOutput(true);
this.setColour(Blockly.Action.HUE);
this.setTooltip(Blockly.Translate('file_data_tooltip'));
//this.setHelpUrl(getHelp('file_data'));
},
/**
* Called whenever anything on the workspace changes.
* Add warning if this flow block is not nested inside a loop.
* @param {!Blockly.Events.Abstract} e Change event.
* @this Blockly.Block
*/
onchange: function(e) {
let legal = false;
// Is the block nested in a trigger?
let block = this;
do {
if (this.FUNCTION_TYPES.includes(block.type)) {
legal = true;
break;
}
block = block.getSurroundParent();
} while (block);

if (legal) {
this.setWarningText(null, this.id);
} else {
this.setWarningText(Blockly.Translate('file_data_warning'), this.id);
}
},
/**
* List of block types that are functions and thus do not need warnings.
* To add a new function type add this to your code:
* Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func');
*/
FUNCTION_TYPES: ['file_read'],
};
Blockly.JavaScript['file_data'] = function(block) {
const attr = block.getFieldValue('ATTR');

return [attr, Blockly.JavaScript.ORDER_ATOMIC];
};

// --- action request --------------------------------------------------
Blockly.Action.blocks['request'] =
'<block type="request">'
Expand Down Expand Up @@ -403,7 +621,7 @@ Blockly.JavaScript['request'] = function(block) {
logText = '';
}

logText += `console.warn('request blockly block is deprecated - please use "http get" instead');\n`;
logText += `console.warn('request blockly block is deprecated - please use "http (GET)" instead');\n`;

if (withStatement === 'TRUE' || withStatement === 'true' || withStatement === true) {
const statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
Expand Down

0 comments on commit 3b10f93

Please sign in to comment.