From 9ec21fe10de70e49c9d25dde375a204efe42ea76 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Thu, 5 Sep 2024 01:16:33 +0200 Subject: [PATCH 01/36] [#341] Added icon for `procedures` plugin. --- platypush/backend/http/webapp/src/assets/icons.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platypush/backend/http/webapp/src/assets/icons.json b/platypush/backend/http/webapp/src/assets/icons.json index ae0568c4d3..fd58b5f7bc 100644 --- a/platypush/backend/http/webapp/src/assets/icons.json +++ b/platypush/backend/http/webapp/src/assets/icons.json @@ -89,6 +89,9 @@ "ping": { "class": "fas fa-server" }, + "procedures": { + "class": "fas fa-gears" + }, "torrent": { "class": "fa fa-magnet" }, From bbc70fe6e6beca61dbc97444b0baa6677342b39a Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Thu, 5 Sep 2024 01:17:35 +0200 Subject: [PATCH 02/36] [UI] The main module should load the config dir and main file paths at startup. --- platypush/backend/http/webapp/src/App.vue | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platypush/backend/http/webapp/src/App.vue b/platypush/backend/http/webapp/src/App.vue index 004394f17f..bbeea48a9b 100644 --- a/platypush/backend/http/webapp/src/App.vue +++ b/platypush/backend/http/webapp/src/App.vue @@ -49,6 +49,8 @@ export default { data() { return { config: {}, + configDir: null, + configFile: null, userAuthenticated: false, connected: false, pwaInstallEvent: null, @@ -85,7 +87,11 @@ export default { }, async initConfig() { - this.config = await this.request('config.get', {}, 60000, false) + this.config = await this.request('config.get', {}, 60000, false); + [this.configDir, this.configFile] = await Promise.all([ + this.request('config.get_config_dir'), + this.request('config.get_config_file'), + ]) this.userAuthenticated = true }, From 3249053eb0c9fc725e637d116580aa10d0e44d92 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Thu, 5 Sep 2024 01:19:26 +0200 Subject: [PATCH 03/36] [UI] Added support for custom HTML and data in `Autocomplete` component. --- .../src/components/elements/Autocomplete.vue | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/elements/Autocomplete.vue b/platypush/backend/http/webapp/src/components/elements/Autocomplete.vue index 71f8605283..ad6c10ec6c 100644 --- a/platypush/backend/http/webapp/src/components/elements/Autocomplete.vue +++ b/platypush/backend/http/webapp/src/components/elements/Autocomplete.vue @@ -20,12 +20,14 @@
- {{ item.substr(0, value.length) }} - {{ item.substr(value?.length || 0) }} + + {{ getItemText(item).substr(0, value.length) }} + {{ getItemText(item).substr(value?.length || 0) }} +
@@ -33,7 +35,6 @@ From b0d9a95331b919256568e5be7b7c0b2addc3e81b Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Thu, 5 Sep 2024 01:32:51 +0200 Subject: [PATCH 10/36] [UI] Added `title` propery to `EditButton` component. --- .../src/components/elements/EditButton.vue | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/elements/EditButton.vue b/platypush/backend/http/webapp/src/components/elements/EditButton.vue index f24bdde683..e7748ddea5 100644 --- a/platypush/backend/http/webapp/src/components/elements/EditButton.vue +++ b/platypush/backend/http/webapp/src/components/elements/EditButton.vue @@ -1,7 +1,9 @@ @@ -9,6 +11,13 @@ ``` --- .../src/components/elements/Draggable.vue | 416 ++++++++++++++++++ .../src/components/elements/Droppable.vue | 174 ++++++++ 2 files changed, 590 insertions(+) create mode 100644 platypush/backend/http/webapp/src/components/elements/Draggable.vue create mode 100644 platypush/backend/http/webapp/src/components/elements/Droppable.vue diff --git a/platypush/backend/http/webapp/src/components/elements/Draggable.vue b/platypush/backend/http/webapp/src/components/elements/Draggable.vue new file mode 100644 index 0000000000..feb37e1899 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/elements/Draggable.vue @@ -0,0 +1,416 @@ + + + + + diff --git a/platypush/backend/http/webapp/src/components/elements/Droppable.vue b/platypush/backend/http/webapp/src/components/elements/Droppable.vue new file mode 100644 index 0000000000..530a177ea5 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/elements/Droppable.vue @@ -0,0 +1,174 @@ + + + From 1133c6019af765d4800e52d7ec7d59301240af0f Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Thu, 5 Sep 2024 01:56:49 +0200 Subject: [PATCH 15/36] [UI] Added general-purpose entity icon editor component. --- .../components/panels/Entities/IconEditor.vue | 260 ++++++++++++++++++ .../src/components/panels/Entities/Modal.vue | 122 ++------ 2 files changed, 276 insertions(+), 106 deletions(-) create mode 100644 platypush/backend/http/webapp/src/components/panels/Entities/IconEditor.vue diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/IconEditor.vue b/platypush/backend/http/webapp/src/components/panels/Entities/IconEditor.vue new file mode 100644 index 0000000000..a547fb0e68 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/panels/Entities/IconEditor.vue @@ -0,0 +1,260 @@ + + + + + diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue b/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue index fd704d6933..94323f2444 100644 --- a/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue +++ b/platypush/backend/http/webapp/src/components/panels/Entities/Modal.vue @@ -20,40 +20,7 @@
-
- Icon - -
-
- - - - - - Supported: image URLs or - FontAwesome icon classes. - - - - -
-
- -
-
- Icon color -
-
- - -
+
@@ -206,14 +173,13 @@ From 15cf611c95354f16ace4ef2b911ad9601933b89e Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Thu, 5 Sep 2024 02:02:44 +0200 Subject: [PATCH 17/36] [#341] [UI] Implemented support for procedure entities. - Added UI panel. - Added support for entity types. - Enhanced ability to edit procedures. - Added ability to create, rename, edit, duplicate and delete stored procedures. - Added support for YAML dumps of non-Python procedures. - Added support for visualizing Python procedures directly in their source files. --- .../src/components/Action/ActionArgs.vue | 29 +- .../src/components/Action/ActionTile.vue | 318 ++++--- .../src/components/Action/ActionsList.vue | 222 +++++ .../src/components/Action/ActionsListItem.vue | 210 +++++ .../webapp/src/components/Action/vars.scss | 16 +- .../http/webapp/src/components/Nav.vue | 5 +- .../components/Procedure/ProcedureDump.vue | 91 ++ .../components/Procedure/ProcedureEditor.vue | 847 +++++++++++++++--- .../Procedure/ProcedureEditorModal.vue | 126 +++ .../src/components/panels/Entities/Index.vue | 1 + .../components/panels/Entities/Procedure.vue | 707 +++++++++++++++ .../components/panels/Procedures/Index.vue | 310 +++++++ 12 files changed, 2624 insertions(+), 258 deletions(-) create mode 100644 platypush/backend/http/webapp/src/components/Action/ActionsList.vue create mode 100644 platypush/backend/http/webapp/src/components/Action/ActionsListItem.vue create mode 100644 platypush/backend/http/webapp/src/components/Procedure/ProcedureDump.vue create mode 100644 platypush/backend/http/webapp/src/components/Procedure/ProcedureEditorModal.vue create mode 100644 platypush/backend/http/webapp/src/components/panels/Entities/Procedure.vue create mode 100644 platypush/backend/http/webapp/src/components/panels/Procedures/Index.vue diff --git a/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue b/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue index d6c2f8bc6e..593bd0bbda 100644 --- a/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue +++ b/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue @@ -1,5 +1,5 @@ diff --git a/platypush/backend/http/webapp/src/components/Action/ReturnTile.vue b/platypush/backend/http/webapp/src/components/Action/ReturnTile.vue new file mode 100644 index 0000000000..a4fce9f216 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/Action/ReturnTile.vue @@ -0,0 +1,138 @@ + + + From 156a6379d00536d645f63fbcda96ca484a0d0ce4 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Fri, 13 Sep 2024 18:19:02 +0200 Subject: [PATCH 24/36] [#341] Added for for/break/continue statements in procedure editor. --- .../src/components/Action/ActionsBlock.vue | 6 + .../src/components/Action/ActionsList.vue | 151 +++++++++++-- .../src/components/Action/BreakTile.vue | 66 ++++++ .../src/components/Action/ConditionBlock.vue | 6 + .../src/components/Action/ConditionTile.vue | 1 - .../src/components/Action/ContinueTile.vue | 66 ++++++ .../src/components/Action/EndBlockTile.vue | 2 +- .../components/Action/ExpressionEditor.vue | 4 +- .../webapp/src/components/Action/ListItem.vue | 2 +- .../src/components/Action/LoopBlock.vue | 204 +++++++++++++++++ .../src/components/Action/LoopEditor.vue | 153 +++++++++++++ .../webapp/src/components/Action/LoopTile.vue | 212 ++++++++++++++++++ .../webapp/src/components/Action/Mixin.vue | 28 ++- .../webapp/src/components/Action/Response.vue | 4 +- .../src/components/Action/ReturnTile.vue | 9 +- .../components/panels/Entities/Procedure.vue | 7 +- .../backend/http/webapp/src/utils/Text.vue | 10 + 17 files changed, 892 insertions(+), 39 deletions(-) create mode 100644 platypush/backend/http/webapp/src/components/Action/BreakTile.vue create mode 100644 platypush/backend/http/webapp/src/components/Action/ContinueTile.vue create mode 100644 platypush/backend/http/webapp/src/components/Action/LoopBlock.vue create mode 100644 platypush/backend/http/webapp/src/components/Action/LoopEditor.vue create mode 100644 platypush/backend/http/webapp/src/components/Action/LoopTile.vue diff --git a/platypush/backend/http/webapp/src/components/Action/ActionsBlock.vue b/platypush/backend/http/webapp/src/components/Action/ActionsBlock.vue index d5f5084872..315bc46a65 100644 --- a/platypush/backend/http/webapp/src/components/Action/ActionsBlock.vue +++ b/platypush/backend/http/webapp/src/components/Action/ActionsBlock.vue @@ -14,6 +14,7 @@ :dragging="dragging" :has-else="hasElse" :indent="indent" + :is-inside-loop="isInsideLoop" :parent="value" :read-only="readOnly" @add-else="$emit('add-else')" @@ -84,6 +85,11 @@ export default { default: 0, }, + isInsideLoop: { + type: Boolean, + default: false, + }, + readOnly: { type: Boolean, default: false, diff --git a/platypush/backend/http/webapp/src/components/Action/ActionsList.vue b/platypush/backend/http/webapp/src/components/Action/ActionsList.vue index d366e87f6d..4efbb453f9 100644 --- a/platypush/backend/http/webapp/src/components/Action/ActionsList.vue +++ b/platypush/backend/http/webapp/src/components/Action/ActionsList.vue @@ -25,6 +25,24 @@ :is-else="true" v-else-if="elses[index]" /> + + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
@@ -76,8 +106,11 @@ import ActionsListItem from "./ActionsListItem" import ActionTile from "./ActionTile" import AddTile from "./AddTile" +import BreakTile from "./BreakTile" import ConditionBlock from "./ConditionBlock" +import ContinueTile from "./ContinueTile" import ListItem from "./ListItem" +import LoopBlock from "./LoopBlock" import Mixin from "./Mixin" import ReturnTile from "./ReturnTile" import Utils from "@/Utils" @@ -103,8 +136,11 @@ export default { ActionsListItem, ActionTile, AddTile, + BreakTile, ConditionBlock, + ContinueTile, ListItem, + LoopBlock, ReturnTile, }, @@ -119,12 +155,17 @@ export default { default: false, }, + hasElse: { + type: Boolean, + default: false, + }, + indent: { type: Number, default: 0, }, - hasElse: { + isInsideLoop: { type: Boolean, default: false, }, @@ -187,6 +228,7 @@ export default { props: { value: action, active: this.isDragging, + isInsideLoop: !!(this.isInsideLoop || this.getFor(action) || this.getWhile(action)), readOnly: this.readOnly, ref: `action-tile-${index}`, spacerBottom: this.visibleBottomSpacers[index], @@ -223,6 +265,11 @@ export default { data.props.indent = this.indent + 1 } + const loop = this.getFor(action) + if (loop) { + data.props.async = loop.async + } + return data }) }, @@ -281,6 +328,16 @@ export default { }, {}) || {} }, + fors() { + return this.newValue?.reduce?.((acc, action, index) => { + if (this.getFor(action)) { + acc[index] = action + } + + return acc + }, {}) || {} + }, + hasChanges() { return this.newStringValue !== this.stringValue }, @@ -301,18 +358,16 @@ export default { return this.dragIndices?.[0] }, + breakIndex() { + return this.getTileIndex((action) => this.isBreak(action)) + }, + + continueIndex() { + return this.getTileIndex((action) => this.isContinue(action)) + }, + returnIndex() { - const ret = this.newValue?.reduce?.((acc, action, index) => { - if (acc >= 0) - return acc - - if (this.isReturn(action)) - return index - - return acc - }, -1) - - return ret >= 0 ? ret : null + return this.getTileIndex((action) => this.isReturn(action)) }, returnValue() { @@ -349,7 +404,22 @@ export default { }, stopIndex() { - return this.returnIndex + if (this.breakIndex != null) + return this.breakIndex + if (this.continueIndex != null) + return this.continueIndex + if (this.returnIndex != null) + return this.returnIndex + + return null + }, + + allowAddButtons() { + return ( + !this.readOnly && + !this.collapsed && + this.stopIndex == null + ) }, visibleActions() { @@ -360,8 +430,11 @@ export default { if ( this.conditions[index] || this.elses[index] || + this.fors[index] || this.isAction(action) || - this.isReturn(action) + this.isReturn(action) || + this.isBreak(action) || + this.isContinue(action) ) { acc[index] = action } @@ -372,16 +445,23 @@ export default { visibleAddButtons() { return { - action: !this.readOnly && !this.collapsed && this.stopIndex == null, - return: !this.readOnly && !this.collapsed && this.stopIndex == null, - condition: !this.readOnly && !this.collapsed && this.stopIndex == null, + action: this.allowAddButtons, + return: this.allowAddButtons, + condition: this.allowAddButtons, + loop: this.allowAddButtons, else: ( - !this.readOnly && - !this.collapsed && + this.allowAddButtons && this.parent && this.getCondition(this.parent) && - !this.hasElse && - this.stopIndex == null + !this.hasElse + ), + break: ( + this.allowAddButtons && + this.isInsideLoop + ), + continue: ( + this.allowAddButtons && + this.isInsideLoop ), } }, @@ -583,6 +663,19 @@ export default { this.selectLastExprEditor() }, + addLoop() { + this.newValue.push({ 'for _ in ${range(10)}': [] }) + this.selectLastExprEditor() + }, + + addBreak() { + this.newValue.push('break') + }, + + addContinue() { + this.newValue.push('continue') + }, + addReturn() { this.newValue.push({ 'return': null }) this.selectLastExprEditor() @@ -606,7 +699,7 @@ export default { newTileElement.click() this.$nextTick(() => { - const exprEditor = newTile.$el?.querySelector('.expr-editor-container') + const exprEditor = newTile.$el?.querySelector('.editor-container') if (!exprEditor) { return } @@ -644,6 +737,20 @@ export default { } }, + getTileIndex(callback) { + const ret = this.newValue?.reduce?.((acc, action, index) => { + if (acc >= 0) + return acc + + if (callback(action)) + return index + + return acc + }, -1) + + return ret >= 0 ? ret : null + }, + syncSpacers() { this.$nextTick(() => { this.spacerElements = Object.keys(this.newValue).reduce((acc, index) => { diff --git a/platypush/backend/http/webapp/src/components/Action/BreakTile.vue b/platypush/backend/http/webapp/src/components/Action/BreakTile.vue new file mode 100644 index 0000000000..4c4fc1cc89 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/Action/BreakTile.vue @@ -0,0 +1,66 @@ + + + diff --git a/platypush/backend/http/webapp/src/components/Action/ConditionBlock.vue b/platypush/backend/http/webapp/src/components/Action/ConditionBlock.vue index d0f6f6e0cc..40fb29189a 100644 --- a/platypush/backend/http/webapp/src/components/Action/ConditionBlock.vue +++ b/platypush/backend/http/webapp/src/components/Action/ConditionBlock.vue @@ -4,6 +4,7 @@ :collapsed="collapsed" :dragging="isDragging" :has-else="hasElse" + :is-inside-loop="isInsideLoop" :indent="indent" :read-only="readOnly" @input="onActionsChange" @@ -107,6 +108,11 @@ export default { default: false, }, + isInsideLoop: { + type: Boolean, + default: false, + }, + readOnly: { type: Boolean, default: false, diff --git a/platypush/backend/http/webapp/src/components/Action/ConditionTile.vue b/platypush/backend/http/webapp/src/components/Action/ConditionTile.vue index 4493b34c38..f33f7c7cb8 100644 --- a/platypush/backend/http/webapp/src/components/Action/ConditionTile.vue +++ b/platypush/backend/http/webapp/src/components/Action/ConditionTile.vue @@ -21,7 +21,6 @@ if [ ] - then diff --git a/platypush/backend/http/webapp/src/components/Action/ContinueTile.vue b/platypush/backend/http/webapp/src/components/Action/ContinueTile.vue new file mode 100644 index 0000000000..1df7dc8654 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/Action/ContinueTile.vue @@ -0,0 +1,66 @@ + + + diff --git a/platypush/backend/http/webapp/src/components/Action/EndBlockTile.vue b/platypush/backend/http/webapp/src/components/Action/EndBlockTile.vue index 4ae3cee4ab..5e3f56f5be 100644 --- a/platypush/backend/http/webapp/src/components/Action/EndBlockTile.vue +++ b/platypush/backend/http/webapp/src/components/Action/EndBlockTile.vue @@ -12,7 +12,7 @@
- + diff --git a/platypush/backend/http/webapp/src/components/Action/ExpressionEditor.vue b/platypush/backend/http/webapp/src/components/Action/ExpressionEditor.vue index 9b1c71ee42..bdf9b9661e 100644 --- a/platypush/backend/http/webapp/src/components/Action/ExpressionEditor.vue +++ b/platypush/backend/http/webapp/src/components/Action/ExpressionEditor.vue @@ -29,7 +29,7 @@ export default { props: { value: { - type: String, + type: [String, Number, Boolean, Object, Array], default: '', }, @@ -83,7 +83,7 @@ export default { mounted() { this.hasChanges = false - if (!this.value?.trim()?.length) { + if (!this.value?.trim?.()?.length) { this.hasChanges = this.allowEmpty } diff --git a/platypush/backend/http/webapp/src/components/Action/ListItem.vue b/platypush/backend/http/webapp/src/components/Action/ListItem.vue index f9354f8696..e938f5b187 100644 --- a/platypush/backend/http/webapp/src/components/Action/ListItem.vue +++ b/platypush/backend/http/webapp/src/components/Action/ListItem.vue @@ -87,7 +87,7 @@ export default { }, value: { - type: [String, Object], + type: [String, Number, Boolean, Object, Array], required: true, }, }, diff --git a/platypush/backend/http/webapp/src/components/Action/LoopBlock.vue b/platypush/backend/http/webapp/src/components/Action/LoopBlock.vue new file mode 100644 index 0000000000..56c5ecdc7f --- /dev/null +++ b/platypush/backend/http/webapp/src/components/Action/LoopBlock.vue @@ -0,0 +1,204 @@ + + + diff --git a/platypush/backend/http/webapp/src/components/Action/LoopEditor.vue b/platypush/backend/http/webapp/src/components/Action/LoopEditor.vue new file mode 100644 index 0000000000..d54803a7de --- /dev/null +++ b/platypush/backend/http/webapp/src/components/Action/LoopEditor.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/platypush/backend/http/webapp/src/components/Action/LoopTile.vue b/platypush/backend/http/webapp/src/components/Action/LoopTile.vue new file mode 100644 index 0000000000..475bede105 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/Action/LoopTile.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/platypush/backend/http/webapp/src/components/Action/Mixin.vue b/platypush/backend/http/webapp/src/components/Action/Mixin.vue index 4911c9a3d2..e4f2cc196e 100644 --- a/platypush/backend/http/webapp/src/components/Action/Mixin.vue +++ b/platypush/backend/http/webapp/src/components/Action/Mixin.vue @@ -6,16 +6,42 @@ export default { return value?.trim?.()?.match(/^if\s*\$\{(.*)\}\s*$/i)?.[1]?.trim?.() }, + getFor(value) { + value = this.getKey(value) || value + let m = value?.trim?.()?.match(/^for(k?)\s*(.*)\s*in\s*\$\{(.*)\}\s*$/i) + if (!m) + return null + + return { + async: m[1].length > 0, + iterator: m[2].trim(), + iterable: m[3].trim(), + } + }, + getKey(value) { return this.isKeyword(value) ? Object.keys(value)[0] : null }, + getWhile(value) { + value = this.getKey(value) || value + return value?.trim?.()?.match(/^while\s*\$\{(.*)\}\s*$/i)?.[1]?.trim?.() + }, + isAction(value) { return typeof value === 'object' && !Array.isArray(value) && (value.action || value.name) }, isActionsBlock(value) { - return this.getCondition(value) || this.isElse(value) + return this.getCondition(value) || this.isElse(value) || this.getFor(value) + }, + + isBreak(value) { + return value?.toLowerCase?.()?.trim?.() === 'break' + }, + + isContinue(value) { + return value?.toLowerCase?.()?.trim?.() === 'continue' }, isKeyword(value) { diff --git a/platypush/backend/http/webapp/src/components/Action/Response.vue b/platypush/backend/http/webapp/src/components/Action/Response.vue index 55ff647fff..93f63b96bf 100644 --- a/platypush/backend/http/webapp/src/components/Action/Response.vue +++ b/platypush/backend/http/webapp/src/components/Action/Response.vue @@ -32,7 +32,7 @@ export default { mixins: [Utils], props: { response: { - type: [String, Object], + type: [String, Object, Array, Number, Boolean], }, error: { @@ -51,7 +51,7 @@ export default { jsonResponse() { if (this.isJSON) { - return hljs.highlight(this.response, {language: 'json'}).value + return hljs.highlight(this.response.toString(), {language: 'json'}).value } return null diff --git a/platypush/backend/http/webapp/src/components/Action/ReturnTile.vue b/platypush/backend/http/webapp/src/components/Action/ReturnTile.vue index a4fce9f216..cd9134c27d 100644 --- a/platypush/backend/http/webapp/src/components/Action/ReturnTile.vue +++ b/platypush/backend/http/webapp/src/components/Action/ReturnTile.vue @@ -19,7 +19,7 @@
-
+
@@ -59,7 +59,7 @@ export default { props: { value: { - type: String, + type: [String, Number, Boolean, Object, Array], default: '', }, @@ -68,11 +68,6 @@ export default { default: false, }, - isElse: { - type: Boolean, - default: false, - }, - readOnly: { type: Boolean, default: false, diff --git a/platypush/backend/http/webapp/src/components/panels/Entities/Procedure.vue b/platypush/backend/http/webapp/src/components/panels/Entities/Procedure.vue index 69dac41ca8..f02715c964 100644 --- a/platypush/backend/http/webapp/src/components/panels/Entities/Procedure.vue +++ b/platypush/backend/http/webapp/src/components/panels/Entities/Procedure.vue @@ -126,7 +126,7 @@
-
Type
+
Source
  {{ value.procedure_type }} @@ -323,7 +323,10 @@ export default { return 'fab fa-python' if (this.value.procedure_type === 'config') - return 'fas fa-rectangle-list' + return 'fas fa-file' + + if (this.value.procedure_type === 'db') + return 'fas fa-database' return this.defaultIconClass }, diff --git a/platypush/backend/http/webapp/src/utils/Text.vue b/platypush/backend/http/webapp/src/utils/Text.vue index 67dfd9d01b..c87ebde287 100644 --- a/platypush/backend/http/webapp/src/utils/Text.vue +++ b/platypush/backend/http/webapp/src/utils/Text.vue @@ -37,6 +37,16 @@ export default { formatNumber(number) { return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") }, + + escapeHTML(value) { + return value + ?.toString?.() + ?.replace?.(/&/g, "&") + ?.replace?.(//g, ">") + ?.replace?.(/"/g, """) + ?.replace?.(/'/g, "'") || '' + }, }, } From dfbbea93fd0ec3f0d5af5892edea25c9351beebe Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Sun, 15 Sep 2024 02:06:23 +0200 Subject: [PATCH 25/36] [#341] Added UI for `while` loops in procedure editor. --- .../src/components/Action/ActionsList.vue | 57 ++++++++++++++--- .../src/components/Action/LoopBlock.vue | 60 ++++++++++++++---- .../webapp/src/components/Action/LoopTile.vue | 61 ++++++++++++++----- .../webapp/src/components/Action/Mixin.vue | 2 +- 4 files changed, 141 insertions(+), 39 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/Action/ActionsList.vue b/platypush/backend/http/webapp/src/components/Action/ActionsList.vue index 4efbb453f9..faa20209b2 100644 --- a/platypush/backend/http/webapp/src/components/Action/ActionsList.vue +++ b/platypush/backend/http/webapp/src/components/Action/ActionsList.vue @@ -29,7 +29,7 @@ v-on="componentsData[index].on" :collapsed="collapsedBlocks[index]" :dragging="isDragging" - v-else-if="fors[index]" /> + v-else-if="loops[index]" />
-
- +
+ +
+ +
+
@@ -265,9 +269,15 @@ export default { data.props.indent = this.indent + 1 } - const loop = this.getFor(action) - if (loop) { - data.props.async = loop.async + const forLoop = this.getFor(action) + if (forLoop) { + data.props.async = forLoop.async + data.props.type = 'for' + } + + const whileLoop = this.getWhile(action) + if (whileLoop) { + data.props.type = 'while' } return data @@ -338,6 +348,23 @@ export default { }, {}) || {} }, + whiles() { + return this.newValue?.reduce?.((acc, action, index) => { + if (this.getWhile(action)) { + acc[index] = action + } + + return acc + }, {}) || {} + }, + + loops() { + return [...Object.keys(this.fors), ...Object.keys(this.whiles)].reduce((acc, index) => { + acc[index] = this.newValue[index] + return acc + }, {}) + }, + hasChanges() { return this.newStringValue !== this.stringValue }, @@ -389,14 +416,17 @@ export default { showAddButtons() { return ( - this.newValue.length === 0 || !this.collapseAddButtons + (this.indent === 0 && this.newValue.length === 0) || !this.collapseAddButtons ) }, showAddButtonsExpander() { return ( !this.readOnly && - this.newValue?.length > 0 && + ( + this.newValue?.length > 0 || + this.indent > 0 + ) && Object.entries(this.visibleAddButtons).filter( ([key, value]) => value && key != 'action' ).length > 1 @@ -431,6 +461,7 @@ export default { this.conditions[index] || this.elses[index] || this.fors[index] || + this.whiles[index] || this.isAction(action) || this.isReturn(action) || this.isBreak(action) || @@ -448,7 +479,8 @@ export default { action: this.allowAddButtons, return: this.allowAddButtons, condition: this.allowAddButtons, - loop: this.allowAddButtons, + for: this.allowAddButtons, + while: this.allowAddButtons, else: ( this.allowAddButtons && this.parent && @@ -663,11 +695,16 @@ export default { this.selectLastExprEditor() }, - addLoop() { + addForLoop() { this.newValue.push({ 'for _ in ${range(10)}': [] }) this.selectLastExprEditor() }, + addWhileLoop() { + this.newValue.push({ 'while ${True}': [] }) + this.selectLastExprEditor() + }, + addBreak() { this.newValue.push('break') }, diff --git a/platypush/backend/http/webapp/src/components/Action/LoopBlock.vue b/platypush/backend/http/webapp/src/components/Action/LoopBlock.vue index 56c5ecdc7f..079fcf6404 100644 --- a/platypush/backend/http/webapp/src/components/Action/LoopBlock.vue +++ b/platypush/backend/http/webapp/src/components/Action/LoopBlock.vue @@ -22,7 +22,7 @@ diff --git a/platypush/backend/http/webapp/src/components/Action/SetVariablesTile.vue b/platypush/backend/http/webapp/src/components/Action/SetVariablesTile.vue new file mode 100644 index 0000000000..f8d8a15416 --- /dev/null +++ b/platypush/backend/http/webapp/src/components/Action/SetVariablesTile.vue @@ -0,0 +1,361 @@ + + + + + From 6dd1d481d50ee52d238024a650e74fe3ad42547e Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Sat, 21 Sep 2024 20:45:50 +0200 Subject: [PATCH 27/36] [#341] Added support for dynamic context in procedure editor components. --- .../src/components/Action/ActionArgs.vue | 42 ++-- .../src/components/Action/ActionEditor.vue | 20 +- .../src/components/Action/ActionTile.vue | 8 + .../src/components/Action/ActionsBlock.vue | 1 + .../src/components/Action/ActionsList.vue | 57 +++++ .../src/components/Action/ActionsListItem.vue | 6 + .../src/components/Action/ConditionBlock.vue | 4 +- .../src/components/Action/ConditionTile.vue | 13 +- .../components/Action/ContextAutocomplete.vue | 170 ++++++++++++++ .../components/Action/ExpressionEditor.vue | 44 ++-- .../webapp/src/components/Action/ListItem.vue | 8 +- .../src/components/Action/LoopBlock.vue | 16 +- .../src/components/Action/LoopEditor.vue | 86 ++++--- .../webapp/src/components/Action/LoopTile.vue | 4 + .../webapp/src/components/Action/Mixin.vue | 36 +++ .../src/components/Action/ReturnTile.vue | 4 + .../components/Action/SetVariablesTile.vue | 48 ++-- .../webapp/src/components/Action/common.scss | 61 ++--- .../components/Procedure/ProcedureEditor.vue | 11 + .../src/components/elements/Autocomplete.vue | 212 ++++++++++-------- .../webapp/src/mixins/Autocomplete/Props.vue | 58 +++++ 21 files changed, 694 insertions(+), 215 deletions(-) create mode 100644 platypush/backend/http/webapp/src/components/Action/ContextAutocomplete.vue create mode 100644 platypush/backend/http/webapp/src/mixins/Autocomplete/Props.vue diff --git a/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue b/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue index 593bd0bbda..89accd0ea2 100644 --- a/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue +++ b/platypush/backend/http/webapp/src/components/Action/ActionArgs.vue @@ -5,14 +5,15 @@
@@ -36,12 +37,13 @@ @input="onExtraArgNameEdit(i, $event.target.value)">