mxrb 0.1.2 → 0.1.4
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.
- checksums.yaml +4 -4
- data/bin/mxrb +458 -10
- data/docs/de-DE/README.md +1 -0
- data/docs/de-DE/oql-sql.md +42 -0
- data/docs/de-DE/project-structure.md +201 -2
- data/docs/de-DE/runtime-ruby.md +104 -0
- data/docs/de-DE/runtime-schema-migrations.md +44 -0
- data/docs/de-DE/validation-matrix.md +42 -4
- data/docs/en-US/README.md +1 -0
- data/docs/en-US/oql-sql.md +41 -0
- data/docs/en-US/project-structure.md +192 -2
- data/docs/en-US/runtime-ruby.md +100 -0
- data/docs/en-US/runtime-schema-migrations.md +41 -0
- data/docs/en-US/validation-matrix.md +39 -4
- data/docs/pt-BR/README.md +1 -0
- data/docs/pt-BR/entity-dsl.md +8 -0
- data/docs/pt-BR/oql-sql.md +41 -0
- data/docs/pt-BR/project-structure.md +197 -2
- data/docs/pt-BR/runtime-ruby.md +108 -0
- data/docs/pt-BR/runtime-schema-migrations.md +40 -0
- data/docs/pt-BR/validation-matrix.md +42 -5
- data/docs/pt-BR/writing.md +28 -0
- data/lib/mxrb/cli/help.rb +426 -0
- data/lib/mxrb/cli/release.rb +137 -0
- data/lib/mxrb/compiler/compatibility_analyzer.rb +1 -1
- data/lib/mxrb/compiler/data_grid_bundle_compiler.rb +8 -1
- data/lib/mxrb/compiler/domain_document_compiler.rb +3 -0
- data/lib/mxrb/compiler/gallery_bundle_compiler.rb +11 -1
- data/lib/mxrb/compiler/generic_widget_bundle_compiler.rb +76 -19
- data/lib/mxrb/compiler/legacy_custom_widget_compiler.rb +159 -0
- data/lib/mxrb/compiler/legacy_data_grid_compiler.rb +43 -7
- data/lib/mxrb/compiler/legacy_page_builder.rb +1248 -23
- data/lib/mxrb/compiler/packager.rb +27 -13
- data/lib/mxrb/compiler/page_bundle_compiler.rb +13 -4
- data/lib/mxrb/compiler/portable_packager.rb +16 -11
- data/lib/mxrb/compiler/web_bundle_builder.rb +5 -1
- data/lib/mxrb/compiler/web_shell_materializer.rb +42 -2
- data/lib/mxrb/compiler/widget_package_extractor.rb +3 -0
- data/lib/mxrb/domain_diagram/lifecycle.rb +272 -0
- data/lib/mxrb/domain_diagram.rb +409 -0
- data/lib/mxrb/dsl/builder.rb +62 -11
- data/lib/mxrb/environment.rb +226 -0
- data/lib/mxrb/exporter.rb +265 -45
- data/lib/mxrb/http/server.rb +107 -0
- data/lib/mxrb/initializer.rb +80 -9
- data/lib/mxrb/integrity/validator.rb +32 -7
- data/lib/mxrb/io/bson_codec.rb +42 -1
- data/lib/mxrb/io/mpr_file.rb +146 -3
- data/lib/mxrb/model/attribute.rb +3 -0
- data/lib/mxrb/model/entity.rb +44 -2
- data/lib/mxrb/model/microflow.rb +3 -1
- data/lib/mxrb/model/module.rb +71 -0
- data/lib/mxrb/model/page.rb +126 -15
- data/lib/mxrb/model/project.rb +3 -0
- data/lib/mxrb/modeler/catalog.rb +178 -0
- data/lib/mxrb/official_marketplace/module_package_importer.rb +23 -12
- data/lib/mxrb/official_marketplace/widget_package_installer.rb +15 -11
- data/lib/mxrb/official_marketplace.rb +9 -3
- data/lib/mxrb/oql/reverse_translator.rb +394 -0
- data/lib/mxrb/oql/server.rb +4 -8
- data/lib/mxrb/oql.rb +32 -4
- data/lib/mxrb/progress.rb +242 -0
- data/lib/mxrb/project_lifecycle.rb +5 -2
- data/lib/mxrb/ruby_app/exporter.rb +1749 -0
- data/lib/mxrb/ruby_app/preset.rb +506 -0
- data/lib/mxrb/ruby_app/session_manager.rb +122 -0
- data/lib/mxrb/ruby_app.rb +1361 -0
- data/lib/mxrb/runtime/access_control.rb +408 -0
- data/lib/mxrb/runtime/native.rb +1015 -93
- data/lib/mxrb/runtime/scheduler.rb +396 -0
- data/lib/mxrb/runtime/schema_migrator.rb +598 -0
- data/lib/mxrb/runtime/shared_store.rb +335 -0
- data/lib/mxrb/runtime/sqlite_store.rb +729 -0
- data/lib/mxrb/scaffold/generator.rb +11 -3
- data/lib/mxrb/team_server.rb +10 -7
- data/lib/mxrb/uml/activity_diagram.rb +118 -0
- data/lib/mxrb/uml/class_diagram.rb +118 -0
- data/lib/mxrb/uml/sequence_diagram.rb +112 -0
- data/lib/mxrb/uml/server.rb +146 -0
- data/lib/mxrb/uml/support.rb +35 -0
- data/lib/mxrb/version.rb +1 -1
- data/lib/mxrb/web_ui/assets/abnfDiagram-N423BO3Z-C4JD3cEC.js +1 -0
- data/lib/mxrb/web_ui/assets/arc-3Z53kgFp.js +1 -0
- data/lib/mxrb/web_ui/assets/architecture-TIHT7OUA-BStBTLea.js +1 -0
- data/lib/mxrb/web_ui/assets/architectureDiagram-T3A2C74G-DBwqnM4J.js +36 -0
- data/lib/mxrb/web_ui/assets/array-BifhSqXX.js +1 -0
- data/lib/mxrb/web_ui/assets/blockDiagram-VBNYF7ZC-DLtuHt-j.js +132 -0
- data/lib/mxrb/web_ui/assets/c4Diagram-5PPSVZJV-ConSk_pe.js +10 -0
- data/lib/mxrb/web_ui/assets/channel-BhPvD7Dt.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-2GRJ4B5K-D2HpWsf_.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-4I5QYGJK-CiIdNwaF.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-5RXB4S5H-Bu_AaEkE.js +231 -0
- data/lib/mxrb/web_ui/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- data/lib/mxrb/web_ui/assets/chunk-6Q2QTUOP-wQkNmt_X.js +88 -0
- data/lib/mxrb/web_ui/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-GF5L2VYU-G8MmiBzU.js +206 -0
- data/lib/mxrb/web_ui/assets/chunk-I66GZJ75-CulcrLPh.js +127 -0
- data/lib/mxrb/web_ui/assets/chunk-JQJVKLGR-ukjzcdlL.js +156 -0
- data/lib/mxrb/web_ui/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-KBJHAD2P-Wm35lYov.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-KEIR6QF5-BICK3FdT.js +161 -0
- data/lib/mxrb/web_ui/assets/chunk-NSK5VX7P-D2nYrCY4.js +2 -0
- data/lib/mxrb/web_ui/assets/chunk-QR6OTTB3-BrdIzg4Q.js +62 -0
- data/lib/mxrb/web_ui/assets/chunk-RYQCIY6F-CCfZMcW6.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-UBXNYLIW-BPEVYsFK.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-W5SLKNZC-2E6OPhA4.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-WRU74C26-CBIvOyWp.js +70 -0
- data/lib/mxrb/web_ui/assets/chunk-XXDRQBXY-pH58XAyl.js +1 -0
- data/lib/mxrb/web_ui/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- data/lib/mxrb/web_ui/assets/classDiagram-JCYQIIEL-xiqo4D89.js +1 -0
- data/lib/mxrb/web_ui/assets/classDiagram-v2-OCEON4UE-xiqo4D89.js +1 -0
- data/lib/mxrb/web_ui/assets/cose-bilkent-JH36ORCC-t_flPpii.js +1 -0
- data/lib/mxrb/web_ui/assets/cynefin-VYW2F7L2-BIqktTEv.js +1 -0
- data/lib/mxrb/web_ui/assets/cynefinDiagram-MW4NZA55-C2d--lut.js +62 -0
- data/lib/mxrb/web_ui/assets/cytoscape.esm-B-NFISlW.js +321 -0
- data/lib/mxrb/web_ui/assets/dagre-Buvkdvvj.js +1 -0
- data/lib/mxrb/web_ui/assets/dagre-VZM6K2ZE-CSz2_tb5.js +4 -0
- data/lib/mxrb/web_ui/assets/defaultLocale-BFoDCU3G.js +1 -0
- data/lib/mxrb/web_ui/assets/diagram-7IWD3JNH-DCt7u7V_.js +30 -0
- data/lib/mxrb/web_ui/assets/diagram-B4RE2ZJO-DqZBqkMu.js +3 -0
- data/lib/mxrb/web_ui/assets/diagram-LBJQPF4R-ClIYbIsI.js +24 -0
- data/lib/mxrb/web_ui/assets/diagram-Q27KOJAE-DFxhvthJ.js +24 -0
- data/lib/mxrb/web_ui/assets/diagram-UB23O5K3-BSUTXptv.js +41 -0
- data/lib/mxrb/web_ui/assets/dist-D2qOEbeJ.js +1 -0
- data/lib/mxrb/web_ui/assets/domain-mGOZ1KCG.css +1 -0
- data/lib/mxrb/web_ui/assets/domain-qsjXhy4v.js +1 -0
- data/lib/mxrb/web_ui/assets/ebnfDiagram-BXEA7PRR-B5reICEi.js +1 -0
- data/lib/mxrb/web_ui/assets/erDiagram-JOGREHBK-Co5Mxn2p.js +85 -0
- data/lib/mxrb/web_ui/assets/eventmodeling-45OFAUF4-C1ylhSks.js +1 -0
- data/lib/mxrb/web_ui/assets/flowDiagram-UKHOOZJN-CHXaJIaS.js +1 -0
- data/lib/mxrb/web_ui/assets/ganttDiagram-PKOTCBZU-DPPPaWaz.js +292 -0
- data/lib/mxrb/web_ui/assets/gitGraph-TEB2WS4Q-qS77ywA9.js +1 -0
- data/lib/mxrb/web_ui/assets/gitGraphDiagram-DS77QQ5N-DpAv6-BT.js +106 -0
- data/lib/mxrb/web_ui/assets/graphlib-DS17s2tU.js +1 -0
- data/lib/mxrb/web_ui/assets/info-DKCQHKI2-C9VD1Y4e.js +1 -0
- data/lib/mxrb/web_ui/assets/infoDiagram-6WML65LV-Bk1kbcCy.js +2 -0
- data/lib/mxrb/web_ui/assets/init-C-OQMol4.js +1 -0
- data/lib/mxrb/web_ui/assets/ishikawaDiagram-WSZJBQD7-0gcISBFR.js +70 -0
- data/lib/mxrb/web_ui/assets/journeyDiagram-NVQOT4AX-Dt0RQnlh.js +139 -0
- data/lib/mxrb/web_ui/assets/jsx-runtime-DV0a5kSb.js +9 -0
- data/lib/mxrb/web_ui/assets/kanban-definition-27J2QSJJ-DIPQM7w9.js +89 -0
- data/lib/mxrb/web_ui/assets/katex-CXMH3UgJ.js +257 -0
- data/lib/mxrb/web_ui/assets/line-C0rYD-tL.js +1 -0
- data/lib/mxrb/web_ui/assets/linear-BPPxWorj.js +1 -0
- data/lib/mxrb/web_ui/assets/map-BaFkSB1l.js +1 -0
- data/lib/mxrb/web_ui/assets/mermaid-parser.core-B_UPzTxa.js +7 -0
- data/lib/mxrb/web_ui/assets/mindmap-definition-FAOFIHXS-CdJRSMuk.js +96 -0
- data/lib/mxrb/web_ui/assets/modeler-BNqHthwk.css +1 -0
- data/lib/mxrb/web_ui/assets/modeler-CQmqflbg.js +1 -0
- data/lib/mxrb/web_ui/assets/ordinal-BDEzSJ7C.js +1 -0
- data/lib/mxrb/web_ui/assets/packet-7NZHBO7P-CwQ4NSBs.js +1 -0
- data/lib/mxrb/web_ui/assets/path-fybaL0A-.js +1 -0
- data/lib/mxrb/web_ui/assets/pegDiagram-VL7TDLO6-D40S7ppx.js +1 -0
- data/lib/mxrb/web_ui/assets/pie-RZYD4A2V-CJroHMKh.js +1 -0
- data/lib/mxrb/web_ui/assets/pieDiagram-7S7Q4E2Y-QB54__BV.js +39 -0
- data/lib/mxrb/web_ui/assets/quadrantDiagram-CIZ2JOQS-DBhDS6ag.js +7 -0
- data/lib/mxrb/web_ui/assets/radar-I7S5WNFK-DdIUwd2d.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-3IZDKUUU-B1Lw6Xyq.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-abnf-AHOZXSZD-CQgQoeak.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-ebnf-EBAXGLYW-D7qEQ2x8.js +1 -0
- data/lib/mxrb/web_ui/assets/railroad-peg-LSFZ7HO6-C005Vxbb.js +1 -0
- data/lib/mxrb/web_ui/assets/railroadDiagram-AXF67PYL-BBP2qk7M.js +1 -0
- data/lib/mxrb/web_ui/assets/requirementDiagram-LRYGKXZP-D2cLsAoI.js +84 -0
- data/lib/mxrb/web_ui/assets/rough.esm-Dy-Kn_BL.js +1 -0
- data/lib/mxrb/web_ui/assets/sankeyDiagram-W5VNT64P-Bpi3FiP2.js +40 -0
- data/lib/mxrb/web_ui/assets/sequenceDiagram-SI44F4Z6-DCRcDlVe.js +162 -0
- data/lib/mxrb/web_ui/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
- data/lib/mxrb/web_ui/assets/src-CvxfUak2.js +1 -0
- data/lib/mxrb/web_ui/assets/stateDiagram-OKZ733FA-C2GCEoxl.js +1 -0
- data/lib/mxrb/web_ui/assets/stateDiagram-v2-UEYNNEHI-D2gWgedh.js +1 -0
- data/lib/mxrb/web_ui/assets/swimlanes-SLNWSIFB-CRI9irEW.js +2 -0
- data/lib/mxrb/web_ui/assets/swimlanesDiagram-ULZ7WXOC-C5Wb_-hZ.js +8 -0
- data/lib/mxrb/web_ui/assets/theme-_mxc7BdY.css +1 -0
- data/lib/mxrb/web_ui/assets/timeline-definition-Z64GVDOM-B1-mNg-h.js +120 -0
- data/lib/mxrb/web_ui/assets/treeView-QDETBFTQ-7CTvIwKq.js +1 -0
- data/lib/mxrb/web_ui/assets/treemap-6X3UGDF4-CtL22pq5.js +1 -0
- data/lib/mxrb/web_ui/assets/uml-C3KAFGTq.js +51 -0
- data/lib/mxrb/web_ui/assets/uml-Dn-qd01X.css +1 -0
- data/lib/mxrb/web_ui/assets/vennDiagram-T6HMQDX7-BzVnUEAy.js +34 -0
- data/lib/mxrb/web_ui/assets/wardley-OPB4EBWU-JNi-QNag.js +1 -0
- data/lib/mxrb/web_ui/assets/wardleyDiagram-T6FBY63Y-BUwmAQ-B.js +78 -0
- data/lib/mxrb/web_ui/assets/xychartDiagram-ELKLHX3M-DEQS8sKp.js +7 -0
- data/lib/mxrb/web_ui/domain.html +15 -0
- data/lib/mxrb/web_ui/modeler.html +16 -0
- data/lib/mxrb/web_ui/uml.html +31 -0
- data/lib/mxrb/web_ui.rb +89 -0
- data/lib/mxrb/widget_certification.rb +208 -0
- data/lib/mxrb/writer.rb +278 -41
- data/lib/mxrb.rb +38 -8
- metadata +157 -5
|
@@ -25,7 +25,9 @@ module Mxrb
|
|
|
25
25
|
@index = source.document_index
|
|
26
26
|
@widget_type = find_widget_type
|
|
27
27
|
@values = property_values(widget['Object'])
|
|
28
|
-
@list_data_source = @values.values.find
|
|
28
|
+
@list_data_source = @values.values.find do |type, value, _metadata|
|
|
29
|
+
type == 'DataSource' && database_list_property(value)
|
|
30
|
+
end&.last
|
|
29
31
|
@component_name = widget_id.to_s.split('.').last
|
|
30
32
|
@module_path = widget_id.to_s.tr('.', '/')
|
|
31
33
|
end
|
|
@@ -60,60 +62,105 @@ module Mxrb
|
|
|
60
62
|
type = @index[IO::BsonCodec.extract_id(property['TypePointer'])]
|
|
61
63
|
next unless type
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
value_type = type.fetch('ValueType', {})
|
|
66
|
+
[type.fetch('PropertyKey'), [value_type['Type'], property['Value'], value_type]]
|
|
64
67
|
end.to_h
|
|
65
68
|
end
|
|
66
69
|
|
|
67
70
|
def supported_property?(pair)
|
|
68
|
-
type, value = pair
|
|
71
|
+
type, value, metadata = pair
|
|
69
72
|
return true if %w[Boolean Integer Decimal Enumeration String System].include?(type)
|
|
70
73
|
return value['DataSource'].nil? || !database_list_property(value).nil? if type == 'DataSource'
|
|
71
74
|
return true if type == 'Association'
|
|
72
75
|
return true if type == 'Attribute' && value['AttributeRef'].nil?
|
|
73
|
-
return true if
|
|
74
|
-
return
|
|
76
|
+
return true if type == 'Selection'
|
|
77
|
+
return value['Icon'].nil? if type == 'Icon'
|
|
78
|
+
return value['Image'].to_s.empty? if type == 'Image'
|
|
79
|
+
return true if %w[Expression TextTemplate].include?(type) && expression_property(type, value, metadata)
|
|
80
|
+
return true if type == 'Attribute' && attribute_property(value, metadata)
|
|
75
81
|
return no_action?(value) || !compiled_action(value).nil? if type == 'Action'
|
|
76
82
|
return array(value['Widgets']).empty? || @render_widgets if type == 'Widgets'
|
|
77
|
-
return
|
|
83
|
+
return supported_objects?(value) if type == 'Object'
|
|
78
84
|
|
|
79
85
|
false
|
|
80
86
|
end
|
|
81
87
|
|
|
82
88
|
def compile_property(pair)
|
|
83
|
-
type, value = pair
|
|
89
|
+
type, value, metadata = pair
|
|
84
90
|
case type
|
|
85
91
|
when 'Boolean' then value['PrimitiveValue'] == 'true'
|
|
86
92
|
when 'Integer' then value['PrimitiveValue'].to_i
|
|
87
93
|
when 'Decimal' then value['PrimitiveValue'].to_f
|
|
88
94
|
when 'Enumeration', 'String' then value['PrimitiveValue'].to_s
|
|
89
|
-
when 'Expression', 'TextTemplate' then raw(expression_property(type, value))
|
|
95
|
+
when 'Expression', 'TextTemplate' then raw(expression_property(type, value, metadata))
|
|
90
96
|
when 'DataSource' then database_list_property(value)&.then { raw(_1) } || :undefined
|
|
91
97
|
when 'Action' then compiled_action(value)&.then { raw(_1) } || :undefined
|
|
92
98
|
when 'Association' then :undefined
|
|
93
|
-
when 'Attribute' then attribute_property(value)&.then { raw(_1) } || :undefined
|
|
94
|
-
when '
|
|
95
|
-
when '
|
|
99
|
+
when 'Attribute' then attribute_property(value, metadata)&.then { raw(_1) } || :undefined
|
|
100
|
+
when 'Selection' then raw(selection_property(value))
|
|
101
|
+
when 'Icon', 'Image' then :undefined
|
|
102
|
+
when 'Widgets' then compile_widgets(value, metadata)
|
|
103
|
+
when 'Object' then compile_objects(value)
|
|
96
104
|
else :undefined
|
|
97
105
|
end
|
|
98
106
|
end
|
|
99
107
|
|
|
100
|
-
def compile_widgets(value)
|
|
108
|
+
def compile_widgets(value, metadata = nil)
|
|
101
109
|
widgets = array(value['Widgets'])
|
|
102
110
|
return [] if widgets.empty?
|
|
103
111
|
|
|
104
|
-
@render_widgets.call(widgets)
|
|
112
|
+
rendered = @render_widgets.call(widgets)
|
|
113
|
+
return rendered unless data_source_bound?(metadata)
|
|
114
|
+
|
|
115
|
+
raw("TemplatedWidgetProperty(#{javascript(
|
|
116
|
+
children: raw("() => #{javascript(rendered)}"), dataSourceId: widget_key, editable: false
|
|
117
|
+
)})")
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def supported_objects?(value)
|
|
121
|
+
array(value['Objects']).all? do |object|
|
|
122
|
+
values = property_values(object)
|
|
123
|
+
!values.empty? && values.values.all? { supported_property?(_1) }
|
|
124
|
+
end
|
|
105
125
|
end
|
|
106
126
|
|
|
107
|
-
def
|
|
127
|
+
def compile_objects(value)
|
|
128
|
+
array(value['Objects']).map do |object|
|
|
129
|
+
values = property_values(object)
|
|
130
|
+
with_list_data_source(values) do
|
|
131
|
+
values.each_with_object({}) do |(key, pair), result|
|
|
132
|
+
compiled = compile_property(pair)
|
|
133
|
+
result[key.to_sym] = compiled unless compiled.equal?(:undefined)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def with_list_data_source(values)
|
|
140
|
+
previous = @list_data_source
|
|
141
|
+
@list_data_source = values.values.find do |type, value, _metadata|
|
|
142
|
+
type == 'DataSource' && database_list_property(value)
|
|
143
|
+
end&.last
|
|
144
|
+
yield
|
|
145
|
+
ensure
|
|
146
|
+
@list_data_source = previous
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def selection_property(value)
|
|
150
|
+
"SelectionProperty(#{javascript(selectionType: value.fetch('Selection', 'None'), dataSourceId: widget_key)})"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def expression_property(type, value, metadata = nil)
|
|
108
154
|
expression = type == 'Expression' ? compile_expression(value['Expression']) : compile_template(value)
|
|
109
155
|
return unless expression
|
|
110
156
|
|
|
157
|
+
list_bound = data_source_bound?(metadata) && @list_data_source
|
|
111
158
|
args = expression_variables(expression).to_h do |variable|
|
|
112
|
-
[variable.to_sym, { widget: @scope, source: 'object' }]
|
|
159
|
+
[variable.to_sym, { widget: list_bound ? widget_key : @scope, source: 'object' }]
|
|
113
160
|
end
|
|
114
|
-
property =
|
|
161
|
+
property = list_bound ? 'ListExpressionProperty' : 'ExpressionProperty'
|
|
115
162
|
config = { expression: { expr: expression, args: } }
|
|
116
|
-
config[:dataSourceId] = widget_key if
|
|
163
|
+
config[:dataSourceId] = widget_key if list_bound
|
|
117
164
|
"#{property}(#{javascript(config)})"
|
|
118
165
|
end
|
|
119
166
|
|
|
@@ -200,11 +247,17 @@ module Mxrb
|
|
|
200
247
|
pieces.compact.reduce { |left, right| { type: 'function', name: '+', parameters: [left, right] } }
|
|
201
248
|
end
|
|
202
249
|
|
|
203
|
-
def attribute_property(value)
|
|
250
|
+
def attribute_property(value, metadata = nil)
|
|
204
251
|
attribute = value.dig('AttributeRef', 'Attribute').to_s
|
|
205
|
-
return unless @scope && attribute.include?('.')
|
|
252
|
+
return unless (@scope || @list_data_source) && attribute.include?('.')
|
|
206
253
|
|
|
207
254
|
entity, _, name = attribute.rpartition('.')
|
|
255
|
+
if data_source_bound?(metadata) && @list_data_source
|
|
256
|
+
return "ListAttributeProperty(#{javascript(
|
|
257
|
+
path: '', entity:, attribute: name, dataSourceId: widget_key, isList: false
|
|
258
|
+
)})"
|
|
259
|
+
end
|
|
260
|
+
|
|
208
261
|
"AttributeProperty(#{javascript(
|
|
209
262
|
scope: @scope, path: '', entity:, attribute: name,
|
|
210
263
|
onChange: { type: 'doNothing', argMap: {}, config: {}, disabledDuringExecution: true },
|
|
@@ -212,6 +265,10 @@ module Mxrb
|
|
|
212
265
|
)})"
|
|
213
266
|
end
|
|
214
267
|
|
|
268
|
+
def data_source_bound?(metadata)
|
|
269
|
+
!metadata.to_h.fetch('DataSourceProperty', '').to_s.empty?
|
|
270
|
+
end
|
|
271
|
+
|
|
215
272
|
def expression_variables(expression)
|
|
216
273
|
case expression
|
|
217
274
|
when Hash
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'zip'
|
|
4
|
+
|
|
5
|
+
module Mxrb
|
|
6
|
+
module Compiler
|
|
7
|
+
# Serializes schema-described Mendix 6/7 custom widgets to their Dojo client contract.
|
|
8
|
+
# rubocop:disable Metrics
|
|
9
|
+
class LegacyCustomWidgetCompiler
|
|
10
|
+
include ModelValues
|
|
11
|
+
|
|
12
|
+
SUPPORTED_TYPES = %w[
|
|
13
|
+
Attribute Boolean Decimal Entity EntityConstraint Enumeration Form Image Integer
|
|
14
|
+
Microflow String System TranslatableString Object
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
attr_reader :widget_id
|
|
18
|
+
|
|
19
|
+
def initialize(source, widget, language:)
|
|
20
|
+
@source = source
|
|
21
|
+
@widget = widget
|
|
22
|
+
@language = language
|
|
23
|
+
@widget_type = widget['Type'] || {}
|
|
24
|
+
@widget_id = @widget_type['WidgetId'].to_s
|
|
25
|
+
@schema_index = schema_index(@widget_type)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def supported?
|
|
29
|
+
!widget_id.empty? && package_module? && properties(@widget['Object']).all? do |property|
|
|
30
|
+
type = property_type(property)
|
|
31
|
+
SUPPORTED_TYPES.include?(type) && supported_value?(type, property['Value'])
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def properties_hash
|
|
36
|
+
properties(@widget['Object']).to_h do |property|
|
|
37
|
+
schema = property_schema(property)
|
|
38
|
+
[schema['PropertyKey'].to_s, compile_value(schema.dig('ValueType', 'Type'), property['Value'])]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def properties(object) = array(object&.fetch('Properties', nil))
|
|
45
|
+
|
|
46
|
+
def property_schema(property)
|
|
47
|
+
@schema_index[IO::BsonCodec.extract_id(property['TypePointer'])] || {}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def property_type(property) = property_schema(property).dig('ValueType', 'Type').to_s
|
|
51
|
+
|
|
52
|
+
def supported_value?(type, value)
|
|
53
|
+
value ||= {}
|
|
54
|
+
return objects(value).all? { supported_object?(_1) } if type == 'Object'
|
|
55
|
+
return !image_uri(value['Image']).nil? if type == 'Image' && !value['Image'].to_s.empty?
|
|
56
|
+
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def supported_object?(object)
|
|
61
|
+
properties(object).all? do |property|
|
|
62
|
+
type = property_type(property)
|
|
63
|
+
SUPPORTED_TYPES.include?(type) && supported_value?(type, property['Value'])
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def compile_value(type, value)
|
|
68
|
+
value ||= {}
|
|
69
|
+
case type
|
|
70
|
+
when 'Boolean' then value['PrimitiveValue'] == 'true'
|
|
71
|
+
when 'Integer' then value['PrimitiveValue'].to_i
|
|
72
|
+
when 'Decimal' then value['PrimitiveValue'].to_f
|
|
73
|
+
when 'Enumeration', 'String', 'System' then value['PrimitiveValue'].to_s
|
|
74
|
+
when 'TranslatableString' then translated(value['TranslatableValue'])
|
|
75
|
+
when 'Entity' then value['EntityPath'].to_s
|
|
76
|
+
when 'EntityConstraint' then value['XPathConstraint'].to_s
|
|
77
|
+
when 'Attribute' then relative_attribute(value['AttributePath'])
|
|
78
|
+
when 'Microflow' then value['Microflow'].to_s
|
|
79
|
+
when 'Form' then value['Form'].to_s
|
|
80
|
+
when 'Image' then value['Image'].to_s.empty? ? '' : image_uri(value['Image'])
|
|
81
|
+
when 'Object' then objects(value).map { compile_object(_1) }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def compile_object(object)
|
|
86
|
+
properties(object).to_h do |property|
|
|
87
|
+
schema = property_schema(property)
|
|
88
|
+
[schema['PropertyKey'].to_s, compile_value(schema.dig('ValueType', 'Type'), property['Value'])]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def objects(value) = array(value&.fetch('Objects', nil))
|
|
93
|
+
|
|
94
|
+
def relative_attribute(path)
|
|
95
|
+
value = path.to_s
|
|
96
|
+
value.split('.').last.to_s
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def translated(text)
|
|
100
|
+
items = array(text&.fetch('Items', nil))
|
|
101
|
+
items.find { _1['LanguageCode'] == @language }&.fetch('Text', '') ||
|
|
102
|
+
items.find { _1['LanguageCode'] == 'en_US' }&.fetch('Text', '') ||
|
|
103
|
+
items.first&.fetch('Text', '') || ''
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def image_uri(reference)
|
|
107
|
+
module_name, collection_name, image_name = reference.to_s.split('.', 3)
|
|
108
|
+
unit = @source.units_of('Images$ImageCollection').find do |candidate|
|
|
109
|
+
candidate.module_name == module_name && candidate.document['Name'] == collection_name
|
|
110
|
+
end
|
|
111
|
+
image = array(unit&.document&.fetch('Images', nil)).find { _1['Name'] == image_name }
|
|
112
|
+
unless image
|
|
113
|
+
return system_image_uri(collection_name, image_name) if module_name == 'System'
|
|
114
|
+
|
|
115
|
+
return
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
"img/#{module_name}$#{image_name}.#{image_format(image)}"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def system_image_uri(collection_name, image_name)
|
|
122
|
+
return if collection_name != 'Images' || image_name.to_s.empty?
|
|
123
|
+
|
|
124
|
+
extension = %w[Error Running Completed Module].include?(image_name) ? 'gif' : 'png'
|
|
125
|
+
"img/System$#{image_name}.#{extension}"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def schema_index(root)
|
|
129
|
+
index = {}
|
|
130
|
+
visit = lambda do |value|
|
|
131
|
+
case value
|
|
132
|
+
when Hash
|
|
133
|
+
id = IO::BsonCodec.extract_id(value['$ID'])
|
|
134
|
+
index[id] = value if id
|
|
135
|
+
value.each_value { visit.call(_1) }
|
|
136
|
+
when Array then value.each { visit.call(_1) }
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
visit.call(root)
|
|
140
|
+
index
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def package_module?
|
|
144
|
+
return true unless @source.is_a?(SourceModel)
|
|
145
|
+
|
|
146
|
+
entry = "#{widget_id.tr('.', '/')}.js"
|
|
147
|
+
root = File.join(File.dirname(@source.path), 'widgets')
|
|
148
|
+
return true if File.file?(File.join(root, entry))
|
|
149
|
+
|
|
150
|
+
Dir.glob(File.join(root, '*.mpk')).any? do |path|
|
|
151
|
+
Zip::File.open(path) { _1.find_entry(entry) }
|
|
152
|
+
rescue Zip::Error
|
|
153
|
+
false
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
# rubocop:enable Metrics
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -21,7 +21,9 @@ module Mxrb
|
|
|
21
21
|
'Forms$GridNewButton' => 'InsertNew',
|
|
22
22
|
'Forms$GridEditButton' => 'EditSelection',
|
|
23
23
|
'Forms$GridDeleteButton' => 'DeleteSelection',
|
|
24
|
-
'Forms$GridActionButton' => 'InvokeAction'
|
|
24
|
+
'Forms$GridActionButton' => 'InvokeAction',
|
|
25
|
+
'Forms$DataGridAddButton' => 'AddRef',
|
|
26
|
+
'Forms$DataGridRemoveButton' => 'DeleteRef'
|
|
25
27
|
}.freeze
|
|
26
28
|
|
|
27
29
|
attr_reader :unsupported
|
|
@@ -38,16 +40,18 @@ module Mxrb
|
|
|
38
40
|
def html
|
|
39
41
|
props = JSON.generate(properties)[1..-2]
|
|
40
42
|
attributes = {
|
|
41
|
-
'data-mendix-id' => widget_id, 'data-mendix-type' =>
|
|
43
|
+
'data-mendix-id' => widget_id, 'data-mendix-type' => client_widget_type,
|
|
42
44
|
'data-mendix-props' => props, 'class' => css_class, 'tabindex' => @widget['TabIndex'].to_i
|
|
43
45
|
}
|
|
44
46
|
"<div #{attributes.map { |key, value| "#{key}='#{escape(value)}'" }.join(' ')}></div>"
|
|
45
47
|
end
|
|
46
48
|
|
|
49
|
+
def id = widget_id
|
|
50
|
+
|
|
47
51
|
private
|
|
48
52
|
|
|
49
53
|
def properties
|
|
50
|
-
{
|
|
54
|
+
result = {
|
|
51
55
|
'friendlyId' => friendly_id, 'entity' => entity, 'schema' => entity_schema,
|
|
52
56
|
'config' => {
|
|
53
57
|
'locale' => @language, 'gridType' => 'Standalone',
|
|
@@ -57,11 +61,14 @@ module Mxrb
|
|
|
57
61
|
'griddata' => columns.map { compile_column(_1) }, 'plugins' => {}
|
|
58
62
|
}
|
|
59
63
|
}
|
|
64
|
+
result['xpathConstraint'] = @widget['SelectableXPathConstraint'].to_s if reference_set?
|
|
65
|
+
result
|
|
60
66
|
end
|
|
61
67
|
|
|
62
68
|
def presentation
|
|
63
69
|
{
|
|
64
|
-
'rows' => @widget['NumberOfRows'].to_i,
|
|
70
|
+
'rows' => @widget['NumberOfRows'].to_i,
|
|
71
|
+
'columns' => template_grid? ? [@widget['NumberOfColumns'].to_i, 1].max : 1,
|
|
65
72
|
'controlbar' => @widget['IsControlBarVisible'] == true,
|
|
66
73
|
'pagingbar' => @widget['IsPagingEnabled'] == true,
|
|
67
74
|
'sortparams' => sort_items, 'searchbar' => !search_elements.empty?,
|
|
@@ -74,6 +81,8 @@ module Mxrb
|
|
|
74
81
|
end
|
|
75
82
|
|
|
76
83
|
def datasource
|
|
84
|
+
return reference_set_datasource if reference_set?
|
|
85
|
+
|
|
77
86
|
type = SOURCE_TYPES[data_source['$Type']]
|
|
78
87
|
@unsupported << data_source['$Type'].to_s unless type
|
|
79
88
|
result = { 'friendlyId' => friendly_id, 'type' => type || 'unsupported', 'path' => entity }
|
|
@@ -136,7 +145,7 @@ module Mxrb
|
|
|
136
145
|
|
|
137
146
|
def button_params(button)
|
|
138
147
|
case button['$Type']
|
|
139
|
-
when 'Forms$GridNewButton', 'Forms$GridEditButton'
|
|
148
|
+
when 'Forms$GridNewButton', 'Forms$GridEditButton', 'Forms$DataGridAddButton'
|
|
140
149
|
{ entity => { 'pageSettings' => page_settings(button['FormSettings']) } }
|
|
141
150
|
when 'Forms$GridActionButton'
|
|
142
151
|
{ entity => { 'action' => client_action(button['Action']),
|
|
@@ -200,7 +209,17 @@ module Mxrb
|
|
|
200
209
|
|
|
201
210
|
def entity
|
|
202
211
|
direct = data_source['EntityPath'] || data_source.dig('EntityRef', 'Entity')
|
|
203
|
-
direct.to_s.empty? ? attribute_path(columns.first).to_s.rpartition('.').first : direct.to_s
|
|
212
|
+
value = direct.to_s.empty? ? attribute_path(columns.first).to_s.rpartition('.').first : direct.to_s
|
|
213
|
+
reference_set? ? value.split('/').last.to_s : value
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def reference_set_datasource
|
|
217
|
+
{
|
|
218
|
+
'friendlyId' => friendly_id, 'path' => entity, 'entity' => entity,
|
|
219
|
+
'reference' => data_source['EntityPath'].to_s.split('/').first.to_s,
|
|
220
|
+
'sort' => sort_items, 'attributes' => columns.map { relative_attribute(attribute_path(_1)) },
|
|
221
|
+
'distinct' => false
|
|
222
|
+
}
|
|
204
223
|
end
|
|
205
224
|
|
|
206
225
|
def entity_schema
|
|
@@ -233,10 +252,27 @@ module Mxrb
|
|
|
233
252
|
def widget_id = "#{@sequence}_#{buttons.length}"
|
|
234
253
|
|
|
235
254
|
def css_class
|
|
236
|
-
[
|
|
255
|
+
[widget_css_class, "mx-name-#{@widget['Name']}", @widget['Class']]
|
|
237
256
|
.map(&:to_s).reject(&:empty?).uniq.join(' ')
|
|
238
257
|
end
|
|
239
258
|
|
|
259
|
+
def client_widget_type
|
|
260
|
+
return 'mxui.widget.TemplateGrid' if template_grid?
|
|
261
|
+
return 'mxui.widget.ReferenceSetSelector' if reference_set?
|
|
262
|
+
|
|
263
|
+
'mxui.widget.DataGrid'
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def widget_css_class
|
|
267
|
+
return 'mx-templategrid' if template_grid?
|
|
268
|
+
return 'mx-referencesetselector' if reference_set?
|
|
269
|
+
|
|
270
|
+
'mx-datagrid'
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def template_grid? = @widget['$Type'] == 'Forms$TemplateGrid'
|
|
274
|
+
def reference_set? = @widget['$Type'] == 'Forms$ReferenceSetSelector'
|
|
275
|
+
|
|
240
276
|
def translated(text)
|
|
241
277
|
items = array(text&.fetch('Items', nil))
|
|
242
278
|
items.find { _1['LanguageCode'] == @language }&.fetch('Text', '') ||
|