Skip to content

Commit 74bd09b

Browse files
authored
Merge pull request #169 from NASA-IMPACT/fix/configure-cms-in-worktrees
Fix Configure CMS to use the deployment port instead of hardcoded 8888
2 parents 123b12c + 9365471 commit 74bd09b

13 files changed

Lines changed: 81 additions & 44 deletions

File tree

.claude/skills/mmgis-deployment/scripts/_lib.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ mw_dashboard_url() {
168168
echo "http://localhost:$((port + 1))"
169169
}
170170

171+
# Configure (CMS) URL for a deployment (served on PORT itself, not PORT+1).
172+
mw_configure_url() {
173+
local port="$1"
174+
echo "http://localhost:${port}/configure"
175+
}
176+
171177
# Poll the API healthcheck until it returns 200 or timeout (seconds).
172178
mw_wait_healthy() {
173179
local port="$1" timeout="${2:-90}" url

.claude/skills/mmgis-deployment/scripts/create.sh

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,25 @@ else
8282
(cd "$dir" && npm install --force)
8383
fi
8484

85+
# --- configure CMS bundle ---
86+
# configure/build is gitignored and the server never builds it live (unlike the
87+
# dashboard), so /configure has no app to serve unless we build one. Always
88+
# build from this worktree's own sources: a bundle copied from another checkout
89+
# goes silently stale whenever either side's configure/src changes. The build
90+
# itself is ~20s; configure/ has its own package.json, so first provision also
91+
# pays an npm install here.
92+
if [ -d "$dir/configure/node_modules" ]; then
93+
mw_info "configure/node_modules present (skipping npm install)"
94+
else
95+
mw_info "running npm install in configure/ (takes a few minutes)..."
96+
(cd "$dir/configure" && npm install)
97+
fi
98+
mw_info "building configure (~20s)..."
99+
(cd "$dir/configure" && npm run build)
100+
85101
echo
86102
echo "ready: $dir"
87-
echo " port $port · db $dbname · dashboard $(mw_dashboard_url "$port") (after start)"
103+
echo " port $port · db $dbname"
104+
echo " dashboard $(mw_dashboard_url "$port") (after start)"
105+
echo " configure $(mw_configure_url "$port") (after start; log in admin / admin)"
88106
echo " start it: $HERE/start.sh \"$dir\""

.claude/skills/mmgis-deployment/scripts/start.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ mkdir -p "$dir/.mmgis"
2121

2222
echo "starting server (port $port) — waiting for healthcheck..."
2323
if mw_wait_healthy "$port" 120; then
24-
echo "up: dashboard $(mw_dashboard_url "$port") · api http://localhost:$port"
24+
echo "up:"
25+
echo " dashboard $(mw_dashboard_url "$port")"
26+
echo " configure $(mw_configure_url "$port") (log in admin / admin)"
27+
echo " api http://localhost:$port"
2528
else
2629
echo "healthcheck did not pass within timeout. Last log lines:" >&2
2730
tail -n 30 "$dir/.mmgis/server.log" >&2 || true

configure/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configure/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "configure",
3-
"version": "4.2.12-20260702",
3+
"version": "4.2.13-20260706",
44
"homepage": "./configure/build",
55
"private": true,
66
"dependencies": {

configure/src/components/SaveBar/Modals/PreviewModal/PreviewModal.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useSelector, useDispatch } from "react-redux";
33

44
import { setModal } from "../../../../core/ConfigureStore";
55
import { publicUrlMainSite } from "../../../../core/constants";
6+
import { getMainSiteBase } from "../../../../core/urls";
67

78
import Dialog from "@mui/material/Dialog";
89
import DialogContent from "@mui/material/DialogContent";
@@ -82,11 +83,7 @@ function MMGIS(props) {
8283
);
8384
});
8485
});
85-
MMGISIframe.src = `${
86-
window.mmgisglobal.NODE_ENV === "development"
87-
? "http://localhost:8889"
88-
: publicUrlMainSite
89-
}/?_preview=true`;
86+
MMGISIframe.src = `${getMainSiteBase(publicUrlMainSite)}/?_preview=true`;
9087
}, [configuration]);
9188

9289
return (

configure/src/core/Maker.js

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { useState } from "react";
2+
import { getApiBase } from "./urls";
23
import { useSelector, useDispatch } from "react-redux";
34
import { makeStyles } from "@mui/styles";
45

@@ -432,14 +433,7 @@ const getComponent = (
432433
</div>
433434
);
434435
case "upload": {
435-
const uploadDomain =
436-
window.mmgisglobal && window.mmgisglobal.NODE_ENV === "development"
437-
? "http://localhost:8888/"
438-
: (window.mmgisglobal && window.mmgisglobal.ROOT_PATH) || "";
439-
const normalizedDomain =
440-
uploadDomain.length > 0 && !uploadDomain.endsWith("/")
441-
? uploadDomain + "/"
442-
: uploadDomain;
436+
const uploadDomain = getApiBase();
443437
return (
444438
<UploadField
445439
label={com.name}
@@ -450,7 +444,7 @@ const getComponent = (
450444
configuration?.msv?.mission
451445
}
452446
subdir={com.subdir}
453-
domain={normalizedDomain}
447+
domain={uploadDomain}
454448
disabled={disabled || isDisabled}
455449
onChange={(p) =>
456450
updateConfiguration(forceField || com.field, p, layer)
@@ -1345,11 +1339,7 @@ const getComponent = (
13451339
</FormControl>
13461340
);
13471341

1348-
let domain =
1349-
window.mmgisglobal.NODE_ENV === "development"
1350-
? "http://localhost:8888/"
1351-
: window.mmgisglobal.ROOT_PATH || "";
1352-
if (domain.length > 0 && !domain.endsWith("/")) domain += "/";
1342+
const domain = getApiBase();
13531343

13541344
let source = "";
13551345
if (window.mmgisglobal.WITH_TITILER === "true") {

configure/src/core/calls.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
let domain =
2-
window.mmgisglobal.NODE_ENV === "development"
3-
? "http://localhost:8888/"
4-
: window.mmgisglobal.ROOT_PATH || "";
5-
if (domain.length > 0 && !domain.endsWith("/")) domain += "/";
1+
import { getApiBase } from "./urls";
2+
3+
const domain = getApiBase();
64

75
const c = {
86
missionPath: "Missions/",

configure/src/core/upload.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
1-
// Computes the API base the same way configure/src/core/calls.js does.
2-
function getDomain() {
3-
let d =
4-
window.mmgisglobal && window.mmgisglobal.NODE_ENV === 'development'
5-
? 'http://localhost:8888/'
6-
: (window.mmgisglobal && window.mmgisglobal.ROOT_PATH) || '';
7-
if (d.length > 0 && !d.endsWith('/')) d += '/';
8-
return d;
9-
}
1+
import { getApiBase } from './urls';
102

113
// Uploads an image File to the generic core upload endpoint, under the given
124
// `mission` and `subdir` (the caller — e.g. a plugin's config field — names its
@@ -16,7 +8,7 @@ export async function uploadImage(file, mission, subdir) {
168
const form = new FormData();
179
form.append('image', file);
1810

19-
const url = `${getDomain()}api/upload?mission=${encodeURIComponent(
11+
const url = `${getApiBase()}api/upload?mission=${encodeURIComponent(
2012
mission,
2113
)}&subdir=${encodeURIComponent(subdir)}`;
2214
const res = await fetch(url, {

configure/src/core/urls.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Single source of truth for backend / base URLs used across the Configure app.
2+
//
3+
// In development the MMGIS server runs on `window.mmgisglobal.PORT` and serves the
4+
// dashboard SPA on `PORT + 1`; in production, requests are relative to `ROOT_PATH`.
5+
// The port is injected per-deployment at render time (see API/Backend/Config/setup.js),
6+
// so deriving URLs from it here keeps the CMS working on any port instead of a
7+
// hardcoded one. Every site that needs a base URL must go through these helpers —
8+
// the old hardcoded `localhost:8888` was duplicated in six places and only failed
9+
// on non-default ports because of that duplication.
10+
11+
const isDev = () =>
12+
Boolean(window.mmgisglobal && window.mmgisglobal.NODE_ENV === "development");
13+
14+
const withTrailingSlash = (s) =>
15+
s.length > 0 && !s.endsWith("/") ? s + "/" : s;
16+
17+
// Base URL for backend / API requests, always trailing-slashed.
18+
// dev -> "http://localhost:<PORT>/" · prod -> "<ROOT_PATH>/"
19+
export function getApiBase() {
20+
const base = isDev()
21+
? `http://localhost:${window.mmgisglobal.PORT}/`
22+
: (window.mmgisglobal && window.mmgisglobal.ROOT_PATH) || "";
23+
return withTrailingSlash(base);
24+
}
25+
26+
// Base URL of the main dashboard site (served on PORT + 1 in dev), NOT
27+
// trailing-slashed. Pass the production value (e.g. publicUrlMainSite) as the
28+
// fallback used outside development.
29+
export function getMainSiteBase(prodFallback = "") {
30+
return isDev()
31+
? `http://localhost:${parseInt(window.mmgisglobal.PORT, 10) + 1}`
32+
: prodFallback;
33+
}

0 commit comments

Comments
 (0)