Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 83 additions & 13 deletions lib/mendix_bridge/backend_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,9 @@ def mount_routes
end
@server.mount_proc("/api/git") { |request, response| git_route(request, response) }
@server.mount_proc("/api/page") { |request, response| page_route(request, response) }
@server.mount_proc("/api/marketplace/install") do |_request, response|
json(
response,
{
ok: false,
message:
"Marketplace installation is disabled in the viewer. " \
"Use mxcli with the guarded Git workflow."
},
status: 403
)
@server.mount_proc("/api/drafts") { |_request, response| drafts(response) }
@server.mount_proc("/api/marketplace/install") do |request, response|
marketplace_install(request, response)
end
@server.mount(
"/",
Expand Down Expand Up @@ -131,7 +123,7 @@ def health(response)
),
layout_persistence: true,
visual_entity_plans: true,
marketplace_install: false,
marketplace_install: source_project ? true : false,
git: git_workflow ? true : false,
page_drafts: true
}
Expand Down Expand Up @@ -379,6 +371,82 @@ def page_route(request, response)
json(response, { error: "invalid JSON payload" }, status: 400)
end

# Lists the reviewable drafts saved by the visual builders so the viewer can
# surface them (they only exist as inventory sidecars otherwise).
def drafts(response)
entity_path = File.join(@inventory_dir, "inventory", "visual-plans.json")
page_path = File.join(@inventory_dir, "inventory", "page-plans.json")
json(
response,
{
entities: File.file?(entity_path) ? JSON.parse(File.read(entity_path)) : {},
pages: File.file?(page_path) ? JSON.parse(File.read(page_path)) : {}
}
)
end

# Guarded marketplace install, Studio Pro-like: downloads the module and
# imports it into the source project via mxcli, then refreshes the inventory
# so the new module shows up in the explorer. Requires confirming Studio Pro
# is closed (the .mpr is locked while it runs).
def marketplace_install(request, response)
return json(response, { error: "method not allowed" }, status: 405) unless
request.request_method == "POST"

payload = JSON.parse(request.body.to_s)
id = payload.fetch("id").to_s
return json(response, { error: "invalid marketplace id" }, status: 422) unless
id.match?(/\A\d+\z/)
unless payload["studio_closed"] == true
return json(
response,
{ ok: false, message: "Confirm Studio Pro is closed before installing." },
status: 403
)
end

project = source_project
return json(response, { error: "source project unavailable" }, status: 503) unless project

arguments = ["marketplace", "install", id]
arguments.concat(["--version", payload["version"].to_s]) if payload["version"]
arguments.concat(["-p", project])
output = run_mxcli(*arguments)
refresh_error = refresh_inventory(project)

json(
response,
{
ok: true,
message: refresh_error || "Module installed and inventory refreshed.",
output: output.lines.last(6).join.strip
}
)
rescue KeyError => error
json(response, { error: "missing parameter: #{error.key}" }, status: 400)
rescue JSON::ParserError
json(response, { error: "invalid JSON payload" }, status: 400)
rescue BackendServerError => error
json(response, { ok: false, message: error.message }, status: 502)
end

def source_project
metadata_path = File.join(@inventory_dir, "mendix-project.json")
return nil unless File.file?(metadata_path)

source = JSON.parse(File.read(metadata_path))["source_project"]
source if source && File.file?(source)
rescue JSON::ParserError
nil
end

def refresh_inventory(project)
Importer.new(mxcli: @mxcli).import(project, @inventory_dir)
nil
rescue StandardError => error
"Module installed, but the inventory refresh failed: #{error.message}"
end

def page_detail(qn)
path = File.join(@inventory_dir, "inventory", "element-details.json")
return nil unless File.file?(path)
Expand Down Expand Up @@ -407,7 +475,9 @@ def check_mdl(mdl)
stdout, stderr, status = Open3.capture3(@mxcli, "check", file.path)
return [true, nil] if status.success?

[false, (stderr.empty? ? stdout : stderr).strip]
output = (stderr.empty? ? stdout : stderr).lines
.reject { |line| line.start_with?("WARNING:") }.join.strip
[false, output]
end
end

Expand Down
12 changes: 12 additions & 0 deletions test/backend_server_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ def test_saves_a_built_page_draft
assert_equal "404", unknown.code
end

def test_lists_saved_drafts
post_json(
"/api/page",
qn: "Module.Home",
content: "container c1 {\n dynamictext t1 (Content: 'Hi')\n}"
)

drafts = get_json("/api/drafts")
assert drafts.key?("entities")
assert_includes drafts["pages"].keys, "Module.Home"
end

def test_health_reports_page_drafts_capability
assert_equal true, get_json("/api/health").dig("capabilities", "page_drafts")
end
Expand Down
Binary file modified web/dist/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 0 additions & 23 deletions web/dist/assets/index-C_CcsZzC.js

This file was deleted.

1 change: 0 additions & 1 deletion web/dist/assets/index-DpBG8tOD.css

This file was deleted.

1 change: 1 addition & 0 deletions web/dist/assets/index-DuDZv5uN.css

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions web/dist/assets/index-xDeQxMQR.js

Large diffs are not rendered by default.

Binary file modified web/dist/brand/mendix-ruby-bridge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web/dist/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions web/dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<meta name="application-name" content="Mendix Ruby Bridge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mendix Ruby Bridge</title>
<script type="module" crossorigin src="/assets/index-C_CcsZzC.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DpBG8tOD.css">
<script type="module" crossorigin src="/assets/index-xDeQxMQR.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DuDZv5uN.css">
</head>
<body>
<div id="root"></div>
Expand Down
Binary file modified web/public/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web/public/brand/mendix-ruby-bridge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified web/public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading