From aaf93ccce6f90cb5ff616b4c9ff1d7e7079e14ee Mon Sep 17 00:00:00 2001 From: Lucie Macron Date: Tue, 25 Mar 2025 17:12:36 +0100 Subject: [PATCH 1/7] fix(example): Fix example 01 to work with vue3 --- examples/01_Widgets/app.py | 36 +- .../{model.yaml => model_vue2.yaml} | 3 +- .../01_Widgets/definitions/model_vue3.yaml | 385 ++++++++++++++++++ .../src/widgets/Select/template.html | 4 +- vue3-components/src/widgets/Slider/script.js | 8 +- .../src/widgets/Slider/template.html | 20 +- .../src/widgets/Switch/template.html | 2 +- 7 files changed, 427 insertions(+), 31 deletions(-) rename examples/01_Widgets/definitions/{model.yaml => model_vue2.yaml} (99%) create mode 100644 examples/01_Widgets/definitions/model_vue3.yaml diff --git a/examples/01_Widgets/app.py b/examples/01_Widgets/app.py index 8e4ed1e..b6d0a09 100644 --- a/examples/01_Widgets/app.py +++ b/examples/01_Widgets/app.py @@ -1,15 +1,24 @@ from pathlib import Path from trame.app import get_server -from trame.ui.vuetify3 import SinglePageLayout -from trame.widgets import vuetify3 as vuetify, simput, html +from trame.widgets import simput, html from trame_simput import get_simput_manager +client_type = "vue3" +use_client2 = client_type == "vue2" + +if use_client2: + from trame.ui.vuetify2 import SinglePageLayout + from trame.widgets import vuetify2 as vuetify +else: + from trame.ui.vuetify3 import SinglePageLayout + from trame.widgets import vuetify3 as vuetify + # ----------------------------------------------------------------------------- # Trame setup # ----------------------------------------------------------------------------- -server = get_server() +server = get_server(client_type=client_type) state, ctrl = server.state, server.controller # ----------------------------------------------------------------------------- @@ -19,17 +28,28 @@ DEF_DIR = Path(__file__).with_name("definitions") simput_manager = get_simput_manager() -simput_manager.load_model(yaml_file=DEF_DIR / "model.yaml") # ----------------------------------------------------------------------------- # Application state # ----------------------------------------------------------------------------- pxm = simput_manager.proxymanager + +def load_model(): + if use_client2: + simput_manager.load_model(yaml_file=DEF_DIR / "model_vue2.yaml") + else: + simput_manager.load_model(yaml_file=DEF_DIR / "model_vue3.yaml") + +load_model() + CHOICES = [] for obj_type in pxm.types(): item = pxm.create(obj_type) - CHOICES.append({"text": obj_type, "value": item.id}) + if use_client2: + CHOICES.append({"text": obj_type, "value": item.id}) + else: + CHOICES.append({"title": obj_type, "value": item.id}) # ----------------------------------------------------------------------------- @@ -40,9 +60,7 @@ def update_ui(use_xml_ui, **kwargs): simput_manager.load_ui(xml_file=DEF_DIR / "ui.xml") else: simput_manager.clear_ui() - simput_manager.load_model( - yaml_file=DEF_DIR / "model.yaml" - ) # Needed to generate UI + load_model() # Needed to generate UI # ----------------------------------------------------------------------------- @@ -115,7 +133,7 @@ def update_ui(use_xml_ui, **kwargs): vuetify.VSelect( v_model=("active", CHOICES[0].get("value")), items=("choices", CHOICES), - dense=True, + variant="underlined", hide_details=True, style="max-width: 120px;", ) diff --git a/examples/01_Widgets/definitions/model.yaml b/examples/01_Widgets/definitions/model_vue2.yaml similarity index 99% rename from examples/01_Widgets/definitions/model.yaml rename to examples/01_Widgets/definitions/model_vue2.yaml index a579416..41a72d3 100644 --- a/examples/01_Widgets/definitions/model.yaml +++ b/examples/01_Widgets/definitions/model_vue2.yaml @@ -361,7 +361,6 @@ Slider: value_range: [-10, 10] level: 2 - ManyDoubleFloat: _label: Many Double floats _help: >- @@ -383,4 +382,4 @@ Slider: level: 2 - type: UI properties: - sizeControl: true \ No newline at end of file + sizeControl: true diff --git a/examples/01_Widgets/definitions/model_vue3.yaml b/examples/01_Widgets/definitions/model_vue3.yaml new file mode 100644 index 0000000..a39c023 --- /dev/null +++ b/examples/01_Widgets/definitions/model_vue3.yaml @@ -0,0 +1,385 @@ +TextField: + SingleString: + _label: Single Text Field String + _help: >- + Example of a String widget with only 1 entry + type: uint8 + initial: 23 + DualHorizontalString: + _label: Dual Text Field for int8 + _help: >- + Example of Text widget with numerical entry + With some multi line example... + size: 2 + type: int8 + initial: + - 1 + - 2 + DualVerticalString: + size: 2 + type: uint8 + initial: + - 8 + - 16 + domains: + - type: UI + properties: + layout: vertical + TripleHorizontalString: + size: 3 + type: float32 + initial: + - 0 + - 0 + - 1 + TripleVerticalString: + size: 3 + type: float64 + initial: + - 0 + - 0 + - 1 + domains: + - type: UI + properties: + layout: vertical + Matrix2: + size: 4 + type: string + initial: + - a + - b + - c + - d + domains: + - type: UI + properties: + layout: l2 + Matrix3: + size: 9 + type: string + initial: + - a + - b + - c + - d + - e + - f + - g + - h + - i + domains: + - type: UI + properties: + layout: l3 + Matrix4: + size: 16 + type: string + initial: + - a + - b + - c + - d + - e + - f + - g + - h + - i + - j + - k + - l + - m + - n + - o + - p + domains: + - type: UI + properties: + layout: l4 + Matrix3Half: + size: 6 + initial: + - a + - b + - c + - d + - e + - f + type: string + domains: + - type: UI + properties: + layout: m3-half + Dynamic: + size: -1 + initial: [] + type: uint32 + domains: + - type: UI + properties: + layout: vertical + sizeControl: true + +Select: + Basic: + _label: Simple Drop Down + _help: >- + Example of a String drop down + type: string + initial: use-case-2 + domains: + - type: LabelList + values: + - title: Case 1 + value: use-case-1 + - title: Case 2 + value: use-case-2 + - title: Case 3 + value: use-case-3 + + Integer: + _label: Simple Number Drop Down + _help: >- + Example of a uint8 drop down + type: uint8 + initial: 2 + domains: + - type: LabelList + values: + - title: Case 1 + value: 1 + - title: Case 2 + value: 2 + - title: Case 3 + value: 3 + + MultiString: + _label: Multi Drop Down + _help: >- + Example of a String drop down + type: string + size: -1 + initial: + - use-case-1 + - use-case-3 + domains: + - type: LabelList + values: + - title: Case 1 + value: use-case-1 + - title: Case 2 + value: use-case-2 + - title: Case 3 + value: use-case-3 + - title: Case 4 + value: use-case-4 + - title: Case 5 + value: use-case-5 + - title: Case 6 + value: use-case-6 + - title: Case 7 + value: use-case-7 + - title: Case 8 + value: use-case-8 + - title: Case 9 + value: use-case-9 + + MultiInteger: + _label: Multi Number Drop Down + _help: >- + Example of a uint8 drop down + type: uint8 + size: -1 + initial: + - 2 + - 4 + domains: + - type: LabelList + values: + - title: Case 1 + value: 1 + - title: Case 2 + value: 2 + - title: Case 3 + value: 3 + - title: Case 4 + value: 4 + + SelectDynamicList: + _label: Dynamic available + _help: Just to try remote domain list + type: string + initial: use-case-1 + domains: + - type: PropertyList # Client handling pointing to existing domain + property: MultiString + +Switch: + BasicOff: + _label: Simple Switch + _help: >- + Example of a switch + type: uint8 + initial: 0 + domains: + - type: Boolean + + BasicOn: + _label: Simple Switch + _help: >- + Example of a switch + type: uint8 + initial: 1 + domains: + - type: Boolean + + BasicOnBool: + _label: On Switch as Bool + _help: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. + type: bool + initial: true + domains: + - type: Boolean + + BasicOffBool: + _label: Off Switch as Bool + _help: >- + Example of a switch + type: bool + initial: false + domains: + - type: Boolean + +TextArea: + BigText1: + _label: Programmable Filter - Request data + _help: >- + This field allow you enter VTK code and describe the + filter processing core. + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. + type: string + initial: Hello + domains: + - type: UI + widget: textarea + properties: + auto-grow: true + rows: 2 + clearable: true + + BigText2: + _label: Programmable Filter - Request information + _help: >- + This field allow you enter VTK code and describe the + information pass logic. + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. + type: string + domains: + - type: UI + widget: textarea + properties: + rows: 5 + +Slider: + Simple: + _label: Single Slider + _help: >- + A small demo with some help + type: uint8 + size: 1 + initial: 128 + domains: + - type: Range + value_range: [0, 255] + level: 2 + + DoubleInt: + _label: Double integers + _help: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. + type: uint8 + size: 2 + initial: [5, 10] + domains: + - type: Range + value_range: [0, 255] + level: 2 + + DoubleFloat: + _label: Double floats + _help: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. + type: float64 + size: 1 + initial: 3.141592654 + domains: + - type: Range + value_range: [-10, 10] + level: 2 + + ManyDoubleFloat: + _label: Many Double floats + _help: >- + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia + deserunt mollit anim id est laborum. + type: float64 + size: -1 + initial: + - 3.141592654 + domains: + - type: Range + value_range: [-10, 10] + level: 2 + - type: UI + properties: + sizeControl: true diff --git a/vue3-components/src/widgets/Select/template.html b/vue3-components/src/widgets/Select/template.html index 0f97ad4..351ff8c 100644 --- a/vue3-components/src/widgets/Select/template.html +++ b/vue3-components/src/widgets/Select/template.html @@ -2,12 +2,12 @@ { - if (Number(props.size.value) !== 1) { + if (Number(props.size) !== 1) { return Math.max(props.size, model.value.length); } return Number(props.size); @@ -217,8 +217,8 @@ export default { dirty(props.name); }; const addEntry = function addEntry() { - props.dynamicSize = model.value.length + 1; - model.value.length = props.dynamicSize; + dynamicSize.value = model.value.length + 1; + model.value.length = dynamicSize.value; validate(dynamicSize.value); }; diff --git a/vue3-components/src/widgets/Slider/template.html b/vue3-components/src/widgets/Slider/template.html index bce75f5..10a34db 100644 --- a/vue3-components/src/widgets/Slider/template.html +++ b/vue3-components/src/widgets/Slider/template.html @@ -1,7 +1,7 @@
- - + +
@@ -22,14 +22,13 @@ {{ model }} - + @@ -63,7 +61,6 @@ v-model="model[i - 1]" @update:modelValue="validate(i)" hide-details - density="compact" :rules="[rule]" :min="computedMin" :max="computedMax" @@ -74,21 +71,18 @@
{{ model[i - 1] }}
- mdi-minus-circle-outline - + /> diff --git a/vue3-components/src/widgets/Switch/template.html b/vue3-components/src/widgets/Switch/template.html index c9615e0..b7a5b3f 100644 --- a/vue3-components/src/widgets/Switch/template.html +++ b/vue3-components/src/widgets/Switch/template.html @@ -6,7 +6,6 @@ :hint="help" v-model="model" @update:modelValue="validate" - density="compact" hide-details :disabled="disabled || !decorator.enable" :readonly="readonly" @@ -14,6 +13,7 @@ Date: Wed, 26 Mar 2025 12:10:51 +0100 Subject: [PATCH 2/7] fix(protocol): fix missing server protocol --- trame_simput/module/core.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trame_simput/module/core.py b/trame_simput/module/core.py index b4b9b50..b0d6af5 100644 --- a/trame_simput/module/core.py +++ b/trame_simput/module/core.py @@ -142,6 +142,8 @@ def push(self, id=None, type=None, domains=None): ) def emit(self, topic, **kwargs): + if not self._server.protocol: + return logger.info("emit: %s", topic) self._server.protocol_call("simput.push.event", topic, **kwargs) From f029b5e07f7e5cff27fa5f7f32aaa84ea02ac523 Mon Sep 17 00:00:00 2001 From: Lucie Macron Date: Wed, 26 Mar 2025 12:11:57 +0100 Subject: [PATCH 3/7] feat(Proxy): support list of proxies with vue3 client --- .gitignore | 2 + examples/07_ProxyList/app.py | 22 +++-- examples/07_ProxyList/definitions/model.yaml | 2 +- .../src/components/Simput/script.js | 1 + .../src/components/SimputItem/template.html | 2 +- vue3-components/src/widgets/Proxy/script.js | 91 ++++++++++++++++++- .../src/widgets/Proxy/template.html | 27 +++++- .../src/widgets/TextField/script.js | 38 ++++++-- .../src/widgets/TextField/template.html | 32 +++---- 9 files changed, 174 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index ecc3046..ff01332 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ pnpm-debug.log* __pycache__ *egg-info *pyc + +*build/* diff --git a/examples/07_ProxyList/app.py b/examples/07_ProxyList/app.py index bcc79d7..0d5e16d 100644 --- a/examples/07_ProxyList/app.py +++ b/examples/07_ProxyList/app.py @@ -1,16 +1,23 @@ from pathlib import Path from trame.app import get_server -from trame.ui.vuetify2 import SinglePageLayout -from trame.widgets import vuetify2 as vuetify, simput +from trame.widgets import simput from trame_simput import get_simput_manager +client_type = "vue3" +use_client2 = client_type == "vue2" +if use_client2: + from trame.ui.vuetify2 import SinglePageLayout + from trame.widgets import vuetify2 as vuetify +else: + from trame.ui.vuetify3 import SinglePageLayout + from trame.widgets import vuetify3 as vuetify # ----------------------------------------------------------------------------- # Trame setup # ----------------------------------------------------------------------------- -server = get_server(client_type="vue2") +server = get_server(client_type=client_type) state, ctrl = server.state, server.controller # ----------------------------------------------------------------------------- @@ -18,7 +25,6 @@ # ----------------------------------------------------------------------------- DEF_DIR = Path(__file__).with_name("definitions") - simput_manager = get_simput_manager() simput_manager.load_model(yaml_file=DEF_DIR / "model.yaml") simput_manager.load_ui(xml_file=DEF_DIR / "ui.xml") @@ -26,13 +32,11 @@ address_book = simput_manager.proxymanager.create("AddressBook") - with SinglePageLayout(server) as layout: simput_widget.register_layout(layout) - with layout.content: - with vuetify.VContainer(fluid=True): - simput.SimputItem(item_id=f"{address_book.id}") - + with layout.content, vuetify.VContainer(fluid=True): + simput.SimputItem(item_id=f"{address_book.id}") + if __name__ == "__main__": server.start() diff --git a/examples/07_ProxyList/definitions/model.yaml b/examples/07_ProxyList/definitions/model.yaml index b1476f8..ea25c6f 100644 --- a/examples/07_ProxyList/definitions/model.yaml +++ b/examples/07_ProxyList/definitions/model.yaml @@ -1,5 +1,5 @@ Person: - _label: Personal Informations + _label: Personal Information FirstName: _label: First Name type: string diff --git a/vue3-components/src/components/Simput/script.js b/vue3-components/src/components/Simput/script.js index 41ad31b..758d546 100644 --- a/vue3-components/src/components/Simput/script.js +++ b/vue3-components/src/components/Simput/script.js @@ -38,6 +38,7 @@ export default { () => emit("query", props.query?.toLowerCase() || ""), 250 ), + managerId, }; const updateManager = function updateManager() { diff --git a/vue3-components/src/components/SimputItem/template.html b/vue3-components/src/components/SimputItem/template.html index 362783a..7b398b6 100644 --- a/vue3-components/src/components/SimputItem/template.html +++ b/vue3-components/src/components/SimputItem/template.html @@ -1,6 +1,6 @@
- {{ data }} +
\ No newline at end of file diff --git a/vue3-components/src/widgets/Proxy/script.js b/vue3-components/src/widgets/Proxy/script.js index 6205831..3a5528f 100644 --- a/vue3-components/src/widgets/Proxy/script.js +++ b/vue3-components/src/widgets/Proxy/script.js @@ -1,7 +1,7 @@ import SimputInput from "../../components/SimputItem/index.vue"; import { useDecorator } from "../../core/utils"; -const { computed, inject, toRef } = window.Vue; +const { computed, inject, toRef, ref } = window.Vue; export default { name: "swProxy", @@ -12,6 +12,17 @@ export default { mtime: { type: Number, }, + size: { + type: Number, + default: 1, + }, + sizeControl: { + type: Boolean, + default: false, + }, + proxyType: { + type: String, + }, }, components: { SimputInput, @@ -27,16 +38,94 @@ export default { name: toRef(props.name), }); + const dynamicSize = ref(props.size); const properties = inject("properties"); + + const model = computed({ + get() { + /* eslint-disable no-unused-expressions */ + props.mtime; // force refresh + dynamicSize.value; + const value = properties() && properties()[props.name]; + if (!value && props.size > 1) { + const emptyArray = []; + emptyArray.length = props.size; + return emptyArray; + } + return value; + }, + set(v) { + properties()[props.name] = v; + }, + }); + const itemId = computed(() => { /* eslint-disable no-unused-expressions */ props.mtime; // force refresh return properties()[props.name]; }); + const computedLayout = computed(() => { + /* eslint-disable no-unused-expressions */ + props.mtime; // force refresh + return props.layout || domains()[props.name]?.UI?.layout || "vertical"; + }); + + const computedSize = computed(() => { + if (Number(props.size) !== 1) { + return Math.max(props.size || 1, model.value.length || 0); + } + return Number(props.size); + }); + + const computedSizeControl = computed(() => { + /* eslint-disable no-unused-expressions */ + props.mtime; // force refresh + return props.sizeControl || domains()[props.name]?.UI?.sizeControl; + }); + + const deleteEntry = function deleteEntry(index) { + if (computedSize.value > Number(props.size)) { + model.value.splice(index, 1); + dirty(props.name); + } + }; + + const getComponentProps = function getComponentProps(index) { + if (computedLayout.value === "vertical") { + return { cols: 12 }; + } + if (computedLayout.value === "l2") { + return { cols: 6 }; + } + if (computedLayout.value === "l3") { + return { cols: 4 }; + } + if (computedLayout.value === "l4") { + return { cols: 3 }; + } + if (computedLayout.value === "m3-half") { + const attrs = { cols: 4 }; + if (index === 3) { + attrs.offset = 4; + } + if (index === 5) { + attrs.offset = 8; + } + return attrs; + } + return {}; + }; + return { itemId, decorator, + model, + computedLayout, + computedSize, + computedSizeControl, + deleteEntry, + getComponentProps, }; }, }; diff --git a/vue3-components/src/widgets/Proxy/template.html b/vue3-components/src/widgets/Proxy/template.html index a2fa372..2860eea 100644 --- a/vue3-components/src/widgets/Proxy/template.html +++ b/vue3-components/src/widgets/Proxy/template.html @@ -1 +1,26 @@ - + + \ No newline at end of file diff --git a/vue3-components/src/widgets/TextField/script.js b/vue3-components/src/widgets/TextField/script.js index 8caadf8..955d1cf 100644 --- a/vue3-components/src/widgets/TextField/script.js +++ b/vue3-components/src/widgets/TextField/script.js @@ -34,7 +34,7 @@ export default { // --- custom to current widget --- editColor: { type: String, - default: "blue lighten-5", + default: "transparent", }, layout: { type: String, @@ -59,6 +59,9 @@ export default { type: Boolean, default: false, }, + proxyType: { + type: String, + }, }, setup(props) { const domains = inject("domains"); @@ -205,17 +208,32 @@ export default { if (!model.value) { model.value = []; } - dynamicSize.value = model.value.length + 1; - model.value.length = dynamicSize.value; - if (props.newValue === "null") { - model.value[model.value.length - 1] = null; - } else if (props.newValue === "same") { - model.value[model.value.length - 1] = - model.value[model.value.length - 2]; + if (props.type == "proxy") { + getSimput() + .wsClient.getConnection() + .getSession() + .call("simput.create_proxy", [ + simputChannel.managerId.value, + props.proxyType, + ]) + .then((proxy_id) => { + if (proxy_id != undefined) { + model.value.push(proxy_id); + dirty(props.name); + } + dynamicSize.value = model.value.length; + validate(dynamicSize.value); + }); + } else { + if (props.newValue === "null") { + model.value.push(null); + } else if (props.newValue === "same") { + model.value.push(model.value[model.value.length - 2]); + } + dynamicSize.value = model.value.length; + validate(dynamicSize.value); } - - validate(dynamicSize.value); }; const deleteEntry = function deletEntry(index) { diff --git a/vue3-components/src/widgets/TextField/template.html b/vue3-components/src/widgets/TextField/template.html index 53d0c9b..0f3a53d 100644 --- a/vue3-components/src/widgets/TextField/template.html +++ b/vue3-components/src/widgets/TextField/template.html @@ -1,14 +1,8 @@ - +
- - mdi-sync - - - mdi-lifebuoy - - - mdi-plus-circle-outline - + + +
@@ -20,7 +14,7 @@
- + + variant="underlined" + /> - mdi-minus-circle-outline - + />
@@ -87,7 +80,6 @@ class="mb-1" :type="levelToType(hint.level)" border="start" - density="compact" > {{ hint.message }}
From f02233a4ffdf20b86075f306eed2312c008b38cf Mon Sep 17 00:00:00 2001 From: Lucie Macron Date: Fri, 18 Apr 2025 09:47:04 +0200 Subject: [PATCH 4/7] style(example): Remove white spaces --- examples/01_Widgets/app.py | 2 ++ examples/07_ProxyList/app.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/01_Widgets/app.py b/examples/01_Widgets/app.py index b6d0a09..55b943b 100644 --- a/examples/01_Widgets/app.py +++ b/examples/01_Widgets/app.py @@ -35,12 +35,14 @@ pxm = simput_manager.proxymanager + def load_model(): if use_client2: simput_manager.load_model(yaml_file=DEF_DIR / "model_vue2.yaml") else: simput_manager.load_model(yaml_file=DEF_DIR / "model_vue3.yaml") + load_model() CHOICES = [] diff --git a/examples/07_ProxyList/app.py b/examples/07_ProxyList/app.py index 0d5e16d..db4d3d5 100644 --- a/examples/07_ProxyList/app.py +++ b/examples/07_ProxyList/app.py @@ -36,7 +36,7 @@ simput_widget.register_layout(layout) with layout.content, vuetify.VContainer(fluid=True): simput.SimputItem(item_id=f"{address_book.id}") - + if __name__ == "__main__": server.start() From 49aaef84da891aa9e7258d2517eb090d6d4fa86e Mon Sep 17 00:00:00 2001 From: Jo-Byr Date: Mon, 12 May 2025 15:35:27 +0200 Subject: [PATCH 5/7] feat(select): support vuetify2-style select in vue3 Support both 'text' and 'title' defined items in sw-select widgets --- examples/01_Widgets/app.py | 5 +- .../{model_vue2.yaml => model.yaml} | 0 .../01_Widgets/definitions/model_vue3.yaml | 385 ------------------ vue3-components/src/widgets/Select/script.js | 5 + .../src/widgets/Select/template.html | 2 + 5 files changed, 8 insertions(+), 389 deletions(-) rename examples/01_Widgets/definitions/{model_vue2.yaml => model.yaml} (100%) delete mode 100644 examples/01_Widgets/definitions/model_vue3.yaml diff --git a/examples/01_Widgets/app.py b/examples/01_Widgets/app.py index 55b943b..7924f60 100644 --- a/examples/01_Widgets/app.py +++ b/examples/01_Widgets/app.py @@ -37,10 +37,7 @@ def load_model(): - if use_client2: - simput_manager.load_model(yaml_file=DEF_DIR / "model_vue2.yaml") - else: - simput_manager.load_model(yaml_file=DEF_DIR / "model_vue3.yaml") + simput_manager.load_model(yaml_file=DEF_DIR / "model.yaml") load_model() diff --git a/examples/01_Widgets/definitions/model_vue2.yaml b/examples/01_Widgets/definitions/model.yaml similarity index 100% rename from examples/01_Widgets/definitions/model_vue2.yaml rename to examples/01_Widgets/definitions/model.yaml diff --git a/examples/01_Widgets/definitions/model_vue3.yaml b/examples/01_Widgets/definitions/model_vue3.yaml deleted file mode 100644 index a39c023..0000000 --- a/examples/01_Widgets/definitions/model_vue3.yaml +++ /dev/null @@ -1,385 +0,0 @@ -TextField: - SingleString: - _label: Single Text Field String - _help: >- - Example of a String widget with only 1 entry - type: uint8 - initial: 23 - DualHorizontalString: - _label: Dual Text Field for int8 - _help: >- - Example of Text widget with numerical entry - With some multi line example... - size: 2 - type: int8 - initial: - - 1 - - 2 - DualVerticalString: - size: 2 - type: uint8 - initial: - - 8 - - 16 - domains: - - type: UI - properties: - layout: vertical - TripleHorizontalString: - size: 3 - type: float32 - initial: - - 0 - - 0 - - 1 - TripleVerticalString: - size: 3 - type: float64 - initial: - - 0 - - 0 - - 1 - domains: - - type: UI - properties: - layout: vertical - Matrix2: - size: 4 - type: string - initial: - - a - - b - - c - - d - domains: - - type: UI - properties: - layout: l2 - Matrix3: - size: 9 - type: string - initial: - - a - - b - - c - - d - - e - - f - - g - - h - - i - domains: - - type: UI - properties: - layout: l3 - Matrix4: - size: 16 - type: string - initial: - - a - - b - - c - - d - - e - - f - - g - - h - - i - - j - - k - - l - - m - - n - - o - - p - domains: - - type: UI - properties: - layout: l4 - Matrix3Half: - size: 6 - initial: - - a - - b - - c - - d - - e - - f - type: string - domains: - - type: UI - properties: - layout: m3-half - Dynamic: - size: -1 - initial: [] - type: uint32 - domains: - - type: UI - properties: - layout: vertical - sizeControl: true - -Select: - Basic: - _label: Simple Drop Down - _help: >- - Example of a String drop down - type: string - initial: use-case-2 - domains: - - type: LabelList - values: - - title: Case 1 - value: use-case-1 - - title: Case 2 - value: use-case-2 - - title: Case 3 - value: use-case-3 - - Integer: - _label: Simple Number Drop Down - _help: >- - Example of a uint8 drop down - type: uint8 - initial: 2 - domains: - - type: LabelList - values: - - title: Case 1 - value: 1 - - title: Case 2 - value: 2 - - title: Case 3 - value: 3 - - MultiString: - _label: Multi Drop Down - _help: >- - Example of a String drop down - type: string - size: -1 - initial: - - use-case-1 - - use-case-3 - domains: - - type: LabelList - values: - - title: Case 1 - value: use-case-1 - - title: Case 2 - value: use-case-2 - - title: Case 3 - value: use-case-3 - - title: Case 4 - value: use-case-4 - - title: Case 5 - value: use-case-5 - - title: Case 6 - value: use-case-6 - - title: Case 7 - value: use-case-7 - - title: Case 8 - value: use-case-8 - - title: Case 9 - value: use-case-9 - - MultiInteger: - _label: Multi Number Drop Down - _help: >- - Example of a uint8 drop down - type: uint8 - size: -1 - initial: - - 2 - - 4 - domains: - - type: LabelList - values: - - title: Case 1 - value: 1 - - title: Case 2 - value: 2 - - title: Case 3 - value: 3 - - title: Case 4 - value: 4 - - SelectDynamicList: - _label: Dynamic available - _help: Just to try remote domain list - type: string - initial: use-case-1 - domains: - - type: PropertyList # Client handling pointing to existing domain - property: MultiString - -Switch: - BasicOff: - _label: Simple Switch - _help: >- - Example of a switch - type: uint8 - initial: 0 - domains: - - type: Boolean - - BasicOn: - _label: Simple Switch - _help: >- - Example of a switch - type: uint8 - initial: 1 - domains: - - type: Boolean - - BasicOnBool: - _label: On Switch as Bool - _help: >- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum. - type: bool - initial: true - domains: - - type: Boolean - - BasicOffBool: - _label: Off Switch as Bool - _help: >- - Example of a switch - type: bool - initial: false - domains: - - type: Boolean - -TextArea: - BigText1: - _label: Programmable Filter - Request data - _help: >- - This field allow you enter VTK code and describe the - filter processing core. - Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum. - type: string - initial: Hello - domains: - - type: UI - widget: textarea - properties: - auto-grow: true - rows: 2 - clearable: true - - BigText2: - _label: Programmable Filter - Request information - _help: >- - This field allow you enter VTK code and describe the - information pass logic. - Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum. - Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum. - type: string - domains: - - type: UI - widget: textarea - properties: - rows: 5 - -Slider: - Simple: - _label: Single Slider - _help: >- - A small demo with some help - type: uint8 - size: 1 - initial: 128 - domains: - - type: Range - value_range: [0, 255] - level: 2 - - DoubleInt: - _label: Double integers - _help: >- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum. - type: uint8 - size: 2 - initial: [5, 10] - domains: - - type: Range - value_range: [0, 255] - level: 2 - - DoubleFloat: - _label: Double floats - _help: >- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum. - type: float64 - size: 1 - initial: 3.141592654 - domains: - - type: Range - value_range: [-10, 10] - level: 2 - - ManyDoubleFloat: - _label: Many Double floats - _help: >- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, quis nostrud exercitation - ullamco laboris nisi ut aliquip ex ea commodo consequat. - Duis aute irure dolor in reprehenderit in voluptate velit - esse cillum dolore eu fugiat nulla pariatur. Excepteur sint - occaecat cupidatat non proident, sunt in culpa qui officia - deserunt mollit anim id est laborum. - type: float64 - size: -1 - initial: - - 3.141592654 - domains: - - type: Range - value_range: [-10, 10] - level: 2 - - type: UI - properties: - sizeControl: true diff --git a/vue3-components/src/widgets/Select/script.js b/vue3-components/src/widgets/Select/script.js index 477a91f..4cc062f 100644 --- a/vue3-components/src/widgets/Select/script.js +++ b/vue3-components/src/widgets/Select/script.js @@ -203,4 +203,9 @@ export default { shouldShow, }; }, + methods: { + resolveItemTitle(item) { + return item.title ?? item.text ?? undefined; + } + }, }; diff --git a/vue3-components/src/widgets/Select/template.html b/vue3-components/src/widgets/Select/template.html index 351ff8c..6de0523 100644 --- a/vue3-components/src/widgets/Select/template.html +++ b/vue3-components/src/widgets/Select/template.html @@ -5,6 +5,8 @@ v-model="model" variant="underlined" :items="computedItems" + :item-title="resolveItemTitle" + item-value="value" :multiple="multiple" @update:modelValue="validate" :hint="computedHelp" From 5904d9871ecf8d527b3a26617c6f1c3327e22a48 Mon Sep 17 00:00:00 2001 From: Jo-Byr Date: Tue, 13 May 2025 10:28:32 +0200 Subject: [PATCH 6/7] feat(select): support vuetify2-style select headers Support 'header' entries in sw-select items list to maintain support from vuetify2 syntax --- examples/01_Widgets/definitions/model.yaml | 23 +++++++++++++++++++ .../src/widgets/Select/template.html | 12 ++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/examples/01_Widgets/definitions/model.yaml b/examples/01_Widgets/definitions/model.yaml index 41a72d3..763648a 100644 --- a/examples/01_Widgets/definitions/model.yaml +++ b/examples/01_Widgets/definitions/model.yaml @@ -205,6 +205,29 @@ Select: - text: Case 4 value: 4 + Section: + _label: Drop Down with sub-sections + _help: >- + Example of a drop down with sub-sections + type: string + size: -1 + initial: + - A + - '1' + domains: + - type: LabelList + values: + - header: Letter cases + - text: Case A + value: A + - text: Case B + value: B + - header: Number cases + - text: Case 1 + value: '1' + - text: Case 2 + value: '2' + SelectDynamicList: _label: Dynamic available _help: Just to try remote domain list diff --git a/vue3-components/src/widgets/Select/template.html b/vue3-components/src/widgets/Select/template.html index 6de0523..3f0d3ce 100644 --- a/vue3-components/src/widgets/Select/template.html +++ b/vue3-components/src/widgets/Select/template.html @@ -13,5 +13,13 @@ :persistent-hint="!!(useRangeHelp || help)" :disabled="disabled || !decorator.enable" :readonly="readonly" - /> - + > + +
+ From 838d512f0e0d8a72e6cfa7ecc140897683e55df3 Mon Sep 17 00:00:00 2001 From: Jo-Byr Date: Thu, 15 May 2025 13:30:13 +0200 Subject: [PATCH 7/7] style(proxy): remove unnecessary ref --- vue3-components/src/widgets/Proxy/script.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/vue3-components/src/widgets/Proxy/script.js b/vue3-components/src/widgets/Proxy/script.js index 3a5528f..0ef442e 100644 --- a/vue3-components/src/widgets/Proxy/script.js +++ b/vue3-components/src/widgets/Proxy/script.js @@ -38,14 +38,12 @@ export default { name: toRef(props.name), }); - const dynamicSize = ref(props.size); const properties = inject("properties"); const model = computed({ get() { /* eslint-disable no-unused-expressions */ props.mtime; // force refresh - dynamicSize.value; const value = properties() && properties()[props.name]; if (!value && props.size > 1) { const emptyArray = [];