158 lines
9.2 KiB
HTML
158 lines
9.2 KiB
HTML
<!-- ════════════ STEP 2: Upstream target ════════════ -->
|
|
<div id="step-panel-2" class="step-pane">
|
|
<div class="step-panel-header">
|
|
<div class="step-panel-eyebrow">
|
|
<div class="step-panel-eyebrow-line"></div>
|
|
<span data-i18n-html="wizard.step_of">Step 2 of 5</span>
|
|
</div>
|
|
<h1 class="step-panel-title" data-i18n="wizard.step2.title">Select upstream & endpoint</h1>
|
|
<p class="step-panel-subtitle" data-i18n="wizard.step2.subtitle">Choose an existing upstream — a shared host with its auth config — or register a new one. Then define the specific endpoint path this operation will call.</p>
|
|
</div>
|
|
|
|
<!-- ── Upstream selector ── -->
|
|
<div class="config-card" style="margin-bottom: 20px; overflow: visible; position: relative; z-index: 10;">
|
|
<div class="config-card-header">
|
|
<div class="config-card-header-icon">
|
|
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="var(--text-secondary)" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
|
|
<rect x="1" y="3" width="14" height="4" rx="1"/>
|
|
<rect x="1" y="9" width="14" height="4" rx="1"/>
|
|
<circle cx="4" cy="5" r="0.8" fill="var(--text-secondary)" stroke="none"/>
|
|
<circle cx="4" cy="11" r="0.8" fill="var(--text-secondary)" stroke="none"/>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<div class="config-card-title">Upstream</div>
|
|
<div class="config-card-subtitle">Shared host, base URL, and authentication</div>
|
|
</div>
|
|
<span class="config-card-optional" style="color: var(--error, #f87171);">Required</span>
|
|
</div>
|
|
<div class="config-card-body" style="gap: 12px; padding: 16px;">
|
|
|
|
<!-- Searchable combobox -->
|
|
<div class="upstream-combobox" id="upstream-combobox">
|
|
<div class="upstream-combobox-trigger" id="upstream-combobox-trigger" onclick="toggleUpstreamDropdown(event)">
|
|
<div class="upstream-combobox-value" id="upstream-combobox-value">
|
|
<span class="upstream-combobox-placeholder">Select an upstream…</span>
|
|
</div>
|
|
<svg class="upstream-combobox-chevron" width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="var(--text-muted)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M4 6l4 4 4-4"/>
|
|
</svg>
|
|
</div>
|
|
|
|
<!-- Dropdown panel -->
|
|
<div class="upstream-dropdown" id="upstream-dropdown" style="display:none;">
|
|
<div class="upstream-search-wrap">
|
|
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="var(--text-muted)" stroke-width="1.8" stroke-linecap="round">
|
|
<circle cx="7" cy="7" r="5"/><path d="M12 12l2.5 2.5"/>
|
|
</svg>
|
|
<input class="upstream-search-input" id="upstream-search" type="text" placeholder="Search by name or URL…" oninput="filterUpstreams(this.value)" autocomplete="off" spellcheck="false">
|
|
</div>
|
|
<div class="upstream-dropdown-list" id="upstream-dropdown-list">
|
|
<!-- populated by JS -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Selected upstream preview -->
|
|
<div class="upstream-preview" id="upstream-preview" style="display:none;">
|
|
<div class="upstream-preview-name" id="upstream-preview-name"></div>
|
|
<div class="upstream-preview-url" id="upstream-preview-url"></div>
|
|
<span class="upstream-auth-badge" id="upstream-preview-badge"></span>
|
|
<button class="upstream-preview-change" onclick="openUpstreamDropdown()">Change</button>
|
|
</div>
|
|
|
|
<!-- Register new upstream trigger row -->
|
|
<div class="upstream-new-trigger" id="upstream-new-trigger" onclick="startNewUpstream()">
|
|
<div class="upstream-new-trigger-radio" id="upstream-new-trigger-radio">
|
|
<div class="upstream-new-trigger-dot"></div>
|
|
</div>
|
|
<svg width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="var(--accent)" stroke-width="2.2" stroke-linecap="round">
|
|
<path d="M8 3v10M3 8h10"/>
|
|
</svg>
|
|
<span>Register new upstream</span>
|
|
</div>
|
|
|
|
<!-- Register new upstream form (kept as-is per design) -->
|
|
<div class="upstream-new-form" id="upstream-new-form" style="display:none;">
|
|
<div class="upstream-new-form-inner">
|
|
<div class="form-row" style="grid-template-columns: 1fr 2fr;">
|
|
<div class="form-group">
|
|
<label class="form-label">Name <span class="form-label-required">required</span></label>
|
|
<input class="form-input" id="new-upstream-name" type="text" placeholder="e.g. acme-api" autocomplete="off" spellcheck="false">
|
|
<div class="form-hint">Unique identifier for this upstream.</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">Base URL <span class="form-label-required">required</span></label>
|
|
<input class="form-input input-mono" id="new-upstream-url" type="text" placeholder="https://api.example.com" autocomplete="off" spellcheck="false">
|
|
<div class="form-hint">Root URL — no trailing slash. Supports <code style="font-family:monospace;font-size:11px;color:var(--accent);">${secrets.*}</code>.</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">Auth headers</label>
|
|
<div class="code-block" style="border-radius: 6px;">
|
|
<div class="code-toolbar">
|
|
<div class="code-dots"><span></span><span></span><span></span></div>
|
|
<span class="code-toolbar-label">json / auth-headers</span>
|
|
</div>
|
|
<textarea class="form-textarea code-textarea" id="new-upstream-auth-headers" rows="7">{
|
|
"Authorization": "${secrets.API_KEY}"
|
|
}</textarea>
|
|
</div>
|
|
<div class="form-hint">These headers are sent on every request to this upstream. Use secrets for credentials.</div>
|
|
</div>
|
|
<div style="display:flex; gap:8px; margin-top:4px;">
|
|
<button class="btn-primary-sm" onclick="saveNewUpstream(event)">Save upstream</button>
|
|
<button class="btn-ghost-sm" onclick="cancelNewUpstream(event)">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── Endpoint ── -->
|
|
<div class="config-card" style="margin-bottom: 20px;">
|
|
<div class="config-card-header">
|
|
<div class="config-card-header-icon">
|
|
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="var(--text-secondary)" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M2 8h12M10 4l4 4-4 4"/>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<div class="config-card-title">Endpoint</div>
|
|
<div class="config-card-subtitle">Path and HTTP method for this specific operation</div>
|
|
</div>
|
|
<span class="config-card-optional" style="color: var(--error, #f87171);">Required</span>
|
|
</div>
|
|
<div class="config-card-body" style="gap: 16px;">
|
|
<div class="form-group">
|
|
<label class="form-label">
|
|
Path template
|
|
<span class="form-label-required">required</span>
|
|
</label>
|
|
<input class="form-input input-mono" id="endpoint-path" type="text" value="/v1/leads" autocomplete="off" spellcheck="false">
|
|
<div class="form-hint">Appended to the upstream base URL. Use <code style="font-family:monospace;font-size:11px;color:var(--accent);">{param}</code> for path variables.</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- /step-pane-2 -->
|
|
|
|
<!-- Template: upstream dropdown item -->
|
|
<template id="tmpl-upstream-item">
|
|
<div class="upstream-dropdown-item">
|
|
<div class="upstream-dropdown-item-info">
|
|
<div class="upstream-dropdown-item-name"></div>
|
|
<div class="upstream-dropdown-item-url"></div>
|
|
</div>
|
|
<span class="upstream-auth-badge"></span>
|
|
<svg class="upstream-dropdown-item-check" width="12" height="12" viewBox="0 0 16 16" fill="none" stroke="var(--accent)" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8l4 4 6-7"/></svg>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- Template: upstream combobox trigger value -->
|
|
<template id="tmpl-upstream-trigger-value">
|
|
<div class="upstream-trigger-name"></div>
|
|
<div class="upstream-trigger-url"></div>
|
|
</template>
|