Skip to content

Commit 6ea005b

Browse files
authored
feat(ui): add configurable launch URL query params (#47)
1 parent f6e05c9 commit 6ea005b

5 files changed

Lines changed: 86 additions & 1 deletion

File tree

helm/spritz/templates/ui-deployment.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ spec:
7474
value: {{ .Values.ui.repoDefaults.branch | quote }}
7575
- name: SPRITZ_UI_HIDE_REPO_INPUTS
7676
value: {{ .Values.ui.repoDefaults.hideInputs | quote }}
77+
- name: SPRITZ_UI_LAUNCH_QUERY_PARAMS
78+
value: {{ .Values.ui.launch.queryParams | toJson | quote }}
7779
{{- if .Values.ui.assetVersion }}
7880
- name: SPRITZ_UI_ASSET_VERSION
7981
value: {{ .Values.ui.assetVersion | quote }}

helm/spritz/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ ui:
241241
dir: ""
242242
branch: ""
243243
hideInputs: false
244+
launch:
245+
queryParams: {}
244246
auth:
245247
mode: none
246248
tokenStorage: localStorage

ui/entrypoint.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ DEFAULT_REPO_URL="${SPRITZ_UI_DEFAULT_REPO_URL:-}"
2424
DEFAULT_REPO_DIR="${SPRITZ_UI_DEFAULT_REPO_DIR:-}"
2525
DEFAULT_REPO_BRANCH="${SPRITZ_UI_DEFAULT_REPO_BRANCH:-}"
2626
HIDE_REPO_INPUTS="${SPRITZ_UI_HIDE_REPO_INPUTS:-}"
27+
LAUNCH_QUERY_PARAMS="${SPRITZ_UI_LAUNCH_QUERY_PARAMS:-}"
2728
ASSET_VERSION="${SPRITZ_UI_ASSET_VERSION:-}"
2829

2930
if [ -z "$API_BASE_URL" ]; then
@@ -60,6 +61,7 @@ DEFAULT_REPO_URL_ESCAPED="$(escape_sed "$DEFAULT_REPO_URL")"
6061
DEFAULT_REPO_DIR_ESCAPED="$(escape_sed "$DEFAULT_REPO_DIR")"
6162
DEFAULT_REPO_BRANCH_ESCAPED="$(escape_sed "$DEFAULT_REPO_BRANCH")"
6263
HIDE_REPO_INPUTS_ESCAPED="$(escape_sed "$HIDE_REPO_INPUTS")"
64+
LAUNCH_QUERY_PARAMS_ESCAPED="$(escape_sed "$LAUNCH_QUERY_PARAMS")"
6365
ASSET_VERSION_ESCAPED="$(escape_sed "$ASSET_VERSION")"
6466

6567
sed "s|__SPRITZ_API_BASE_URL__|${API_BASE_URL_ESCAPED}|g" /usr/share/nginx/html/config.js \
@@ -73,6 +75,7 @@ sed "s|__SPRITZ_API_BASE_URL__|${API_BASE_URL_ESCAPED}|g" /usr/share/nginx/html/
7375
| sed "s|__SPRITZ_UI_DEFAULT_REPO_DIR__|${DEFAULT_REPO_DIR_ESCAPED}|g" \
7476
| sed "s|__SPRITZ_UI_DEFAULT_REPO_BRANCH__|${DEFAULT_REPO_BRANCH_ESCAPED}|g" \
7577
| sed "s|__SPRITZ_UI_HIDE_REPO_INPUTS__|${HIDE_REPO_INPUTS_ESCAPED}|g" \
78+
| sed "s|__SPRITZ_UI_LAUNCH_QUERY_PARAMS__|${LAUNCH_QUERY_PARAMS_ESCAPED}|g" \
7679
| sed "s|__SPRITZ_UI_AUTH_LOGIN_URL__|${AUTH_LOGIN_URL_ESCAPED}|g" \
7780
| sed "s|__SPRITZ_UI_AUTH_RETURN_TO_MODE__|${AUTH_RETURN_TO_MODE_ESCAPED}|g" \
7881
| sed "s|__SPRITZ_UI_AUTH_RETURN_TO_PARAM__|${AUTH_RETURN_TO_PARAM_ESCAPED}|g" \

ui/public/app.js

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ const defaultRepoUrl = String(repoDefaults.url || '').trim();
2323
const defaultRepoDir = String(repoDefaults.dir || '').trim();
2424
const defaultRepoBranch = String(repoDefaults.branch || '').trim();
2525
const hideRepoInputs = parseBoolean(repoDefaults.hideInputs, false);
26+
const launchQueryParamsPlaceholder = '__SPRITZ_UI_LAUNCH_QUERY_PARAMS__';
27+
const launchConfig = config.launch || {};
28+
const launchQueryParams = parseTemplateMap(launchConfig.queryParams);
2629
const authReturnToPlaceholder = '__SPRITZ_RETURN_TO__';
2730
const noticeEl = document.getElementById('notice');
2831
const listEl = document.getElementById('list');
@@ -421,6 +424,33 @@ function parseStorageKeys(value) {
421424
.filter(Boolean);
422425
}
423426

427+
function normalizeTemplateMap(value) {
428+
if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
429+
const normalized = {};
430+
for (const [key, raw] of Object.entries(value)) {
431+
const name = String(key || '').trim();
432+
if (!name) continue;
433+
if (raw === undefined || raw === null) continue;
434+
normalized[name] = String(raw);
435+
}
436+
return normalized;
437+
}
438+
439+
function parseTemplateMap(value) {
440+
if (!value) return {};
441+
if (typeof value === 'object') {
442+
return normalizeTemplateMap(value);
443+
}
444+
const trimmed = String(value).trim();
445+
if (!trimmed || trimmed === launchQueryParamsPlaceholder) return {};
446+
try {
447+
const parsed = JSON.parse(trimmed);
448+
return normalizeTemplateMap(parsed);
449+
} catch {
450+
return {};
451+
}
452+
}
453+
424454
function parsePresets(raw) {
425455
if (Array.isArray(raw)) return raw;
426456
if (typeof raw === 'string') {
@@ -863,6 +893,51 @@ async function fetchSpritzes() {
863893
}
864894
}
865895

896+
function applyTemplatePlaceholders(template, context) {
897+
if (!template) return '';
898+
return String(template).replace(/\{([a-zA-Z0-9_]+)\}/g, (_, key) => {
899+
const value = context[key];
900+
if (value === undefined || value === null) return '';
901+
return String(value);
902+
});
903+
}
904+
905+
function buildOpenUrl(rawUrl, spritz) {
906+
const input = String(rawUrl || '').trim();
907+
if (!input) return '';
908+
let url;
909+
try {
910+
url = new URL(input, window.location.href);
911+
} catch {
912+
return input;
913+
}
914+
const queryEntries = Object.entries(launchQueryParams);
915+
if (!queryEntries.length) {
916+
return url.href;
917+
}
918+
const name = String(spritz?.metadata?.name || '').trim();
919+
const namespace = String(spritz?.metadata?.namespace || '').trim();
920+
const context = {
921+
origin: url.origin,
922+
host: url.host,
923+
hostname: url.hostname,
924+
path: url.pathname,
925+
query: url.search,
926+
name,
927+
namespace,
928+
name_encoded: encodeURIComponent(name),
929+
namespace_encoded: encodeURIComponent(namespace),
930+
path_encoded: encodeURIComponent(url.pathname),
931+
ui_origin: window.location.origin,
932+
ws_origin: url.origin.replace(/^http/i, 'ws'),
933+
};
934+
for (const [param, template] of queryEntries) {
935+
const value = applyTemplatePlaceholders(template, context);
936+
url.searchParams.set(param, value);
937+
}
938+
return url.href;
939+
}
940+
866941
function renderList(items) {
867942
updateKnownSpritzNames(items);
868943
if (!items.length) {
@@ -891,7 +966,7 @@ function renderList(items) {
891966
const openBtn = document.createElement('button');
892967
openBtn.textContent = 'Open';
893968
openBtn.onclick = () => {
894-
const url = spritz.status?.url;
969+
const url = buildOpenUrl(spritz.status?.url, spritz);
895970
if (url) window.open(url, '_blank');
896971
};
897972

ui/public/config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ window.SPRITZ_CONFIG = {
88
branch: '__SPRITZ_UI_DEFAULT_REPO_BRANCH__',
99
hideInputs: '__SPRITZ_UI_HIDE_REPO_INPUTS__',
1010
},
11+
launch: {
12+
queryParams: '__SPRITZ_UI_LAUNCH_QUERY_PARAMS__',
13+
},
1114
auth: {
1215
mode: '__SPRITZ_UI_AUTH_MODE__',
1316
tokenStorage: '__SPRITZ_UI_AUTH_TOKEN_STORAGE__',

0 commit comments

Comments
 (0)