Polish community UI copy and cleanup
Deploy / deploy (push) Successful in 1m36s
CI / Rust Checks (push) Successful in 4m50s
CI / UI Checks (push) Successful in 5s
CI / Deployment Manifests (push) Successful in 2s
CI / Frontend E2E (push) Failing after 5m5s

This commit is contained in:
github-ops
2026-06-19 21:15:02 +00:00
parent 66dd0deee5
commit d072d142ca
57 changed files with 710 additions and 6773 deletions
+46 -46
View File
@@ -1,12 +1,12 @@
<!-- ════════════ STEP 2: Upstream target ════════════ -->
<!-- ════════════ STEP 2: API host ════════════ -->
<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-step-counter>Step 2 of 5</span>
</div>
<h1 class="step-panel-title" data-i18n="wizard.step2.title">Select upstream &amp; 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>
<h1 class="step-panel-title" data-i18n="wizard.step2.title">Выберите API-хост и путь</h1>
<p class="step-panel-subtitle" data-i18n="wizard.step2.subtitle">Выберите существующий API-хост или добавьте новый. Затем задайте путь, который будет вызывать эта операция.</p>
</div>
<!-- ── Upstream selector ── -->
@@ -21,10 +21,10 @@
</svg>
</div>
<div>
<div class="config-card-title" data-i18n="wizard.step2.upstream_title">Upstream</div>
<div class="config-card-subtitle" data-i18n="wizard.step2.upstream_subtitle">Shared host, base URL, and authentication</div>
<div class="config-card-title" data-i18n="wizard.step2.upstream_title">API-хост</div>
<div class="config-card-subtitle" data-i18n="wizard.step2.upstream_subtitle">Базовый URL и способ авторизации</div>
</div>
<span class="config-card-optional" style="color: var(--error, #f87171);" data-i18n="wizard.required">Required</span>
<span class="config-card-optional" style="color: var(--error, #f87171);" data-i18n="wizard.required">Обязательно</span>
</div>
<div class="config-card-body" style="gap: 12px; padding: 16px;">
@@ -32,7 +32,7 @@
<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" data-i18n="wizard.step2.upstream_placeholder">Select an upstream</span>
<span class="upstream-combobox-placeholder" data-i18n="wizard.step2.upstream_placeholder">Выберите API-хост</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"/>
@@ -45,7 +45,7 @@
<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" data-i18n-ph="wizard.step2.search_placeholder" placeholder="Search by name or URL…" oninput="filterUpstreams(this.value)" autocomplete="off" spellcheck="false">
<input class="upstream-search-input" id="upstream-search" type="text" data-i18n-ph="wizard.step2.search_placeholder" placeholder="Поиск по имени или URL…" oninput="filterUpstreams(this.value)" autocomplete="off" spellcheck="false">
</div>
<div class="upstream-dropdown-list" id="upstream-dropdown-list">
<!-- populated by JS -->
@@ -58,7 +58,7 @@
<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="beginEditSelectedUpstream(event)" data-i18n="wizard.step2.change">Change</button>
<button class="upstream-preview-change" onclick="beginEditSelectedUpstream(event)" data-i18n="wizard.step2.change">Изменить</button>
</div>
<!-- Register new upstream trigger row -->
@@ -69,7 +69,7 @@
<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 data-i18n="wizard.step2.register_new">Register new upstream</span>
<span data-i18n="wizard.step2.register_new">Добавить новый API-хост</span>
</div>
<!-- Register new upstream form (kept as-is per design) -->
@@ -77,86 +77,86 @@
<div class="upstream-new-form-inner">
<div class="form-row" style="grid-template-columns: 1fr 2fr;">
<div class="form-group">
<label class="form-label"><span data-i18n="wizard.step2.name">Name</span> <span class="form-label-required" data-i18n="workspace_setup.required">required</span></label>
<label class="form-label"><span data-i18n="wizard.step2.name">Имя</span> <span class="form-label-required" data-i18n="workspace_setup.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" data-i18n="wizard.step2.unique_hint">Unique identifier for this upstream.</div>
<div class="form-hint" data-i18n="wizard.step2.unique_hint">Уникальное имя этого API-хоста.</div>
</div>
<div class="form-group">
<label class="form-label"><span data-i18n="wizard.step2.base_url">Base URL</span> <span class="form-label-required" data-i18n="workspace_setup.required">required</span></label>
<label class="form-label"><span data-i18n="wizard.step2.base_url">Базовый URL</span> <span class="form-label-required" data-i18n="workspace_setup.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" data-i18n="wizard.step2.base_url_hint">Root URL without a trailing slash. Auth is configured separately below.</div>
<div class="form-hint" data-i18n="wizard.step2.base_url_hint">Корневой URL без завершающего слеша. Авторизация настраивается ниже.</div>
</div>
</div>
<div class="form-group">
<label class="form-label" data-i18n="wizard.step2.auth_selector">Upstream auth</label>
<label class="form-label" data-i18n="wizard.step2.auth_selector">Авторизация API-хоста</label>
<select class="form-select" id="new-upstream-auth-mode" data-testid="wizard-auth-mode-select" onchange="updateUpstreamAuthUi()">
<option value="none" data-i18n="wizard.step2.auth_mode.none">No auth</option>
<option value="existing" data-i18n="wizard.step2.auth_mode.existing">Use existing auth profile</option>
<option value="create" data-i18n="wizard.step2.auth_mode.create">Create auth profile now</option>
<option value="none" data-i18n="wizard.step2.auth_mode.none">Без авторизации</option>
<option value="existing" data-i18n="wizard.step2.auth_mode.existing">Использовать существующий профиль авторизации</option>
<option value="create" data-i18n="wizard.step2.auth_mode.create">Создать профиль авторизации сейчас</option>
</select>
<div class="form-hint" data-i18n="wizard.step2.auth_selector_hint">Use secrets-backed auth profiles instead of embedding credential headers in the upstream definition.</div>
<div class="form-hint" data-i18n="wizard.step2.auth_selector_hint">Используйте секреты, чтобы не хранить токены и пароли прямо в настройках API-хоста.</div>
</div>
<div class="form-group" id="upstream-auth-existing-group" hidden>
<label class="form-label" data-i18n="wizard.step2.auth_profile">Auth profile</label>
<label class="form-label" data-i18n="wizard.step2.auth_profile">Профиль авторизации</label>
<select class="form-select" id="new-upstream-auth-profile" data-testid="wizard-auth-profile-select"></select>
<div class="form-hint" id="new-upstream-auth-profile-hint" data-i18n="wizard.step2.auth_profile_hint">Selected profile will be resolved at runtime and attached through `execution_config.auth_profile_ref`.</div>
<div class="form-hint" id="new-upstream-auth-profile-hint" data-i18n="wizard.step2.auth_profile_hint">Выбранный профиль применяется автоматически при каждом вызове инструмента.</div>
</div>
<div class="config-card" id="upstream-auth-create-group" hidden style="margin-top: 6px;">
<div class="config-card-header">
<div>
<div class="config-card-title" data-i18n="wizard.step2.create_profile_title">Create auth profile</div>
<div class="config-card-subtitle" data-i18n="wizard.step2.create_profile_subtitle">Create a reusable profile backed by encrypted workspace secrets.</div>
<div class="config-card-title" data-i18n="wizard.step2.create_profile_title">Создать профиль авторизации</div>
<div class="config-card-subtitle" data-i18n="wizard.step2.create_profile_subtitle">Профиль можно переиспользовать в нескольких API-хостах. Значения берутся из зашифрованных секретов воркспейса.</div>
</div>
</div>
<div class="config-card-body" style="gap: 14px;">
<div class="form-group">
<label class="form-label"><span data-i18n="wizard.step2.profile_name">Profile name</span> <span class="form-label-required" data-i18n="workspace_setup.required">required</span></label>
<label class="form-label"><span data-i18n="wizard.step2.profile_name">Имя профиля</span> <span class="form-label-required" data-i18n="workspace_setup.required">обязательно</span></label>
<input class="form-input" id="new-auth-profile-name" type="text" autocomplete="off" spellcheck="false">
</div>
<div class="form-row" style="grid-template-columns: 1fr 1fr;">
<div class="form-group">
<label class="form-label"><span data-i18n="wizard.step2.profile_kind">Auth kind</span> <span class="form-label-required" data-i18n="workspace_setup.required">required</span></label>
<label class="form-label"><span data-i18n="wizard.step2.profile_kind">Тип авторизации</span> <span class="form-label-required" data-i18n="workspace_setup.required">обязательно</span></label>
<select class="form-select" id="new-auth-profile-kind" data-testid="wizard-auth-profile-kind-select" onchange="updateAuthProfileCreateUi()">
<option value="bearer" data-i18n="wizard.step2.auth_kind.bearer">Bearer token</option>
<option value="basic" data-i18n="wizard.step2.auth_kind.basic">Basic auth</option>
<option value="api_key_header" data-i18n="wizard.step2.auth_kind.api_key_header">API key header</option>
<option value="api_key_query" data-i18n="wizard.step2.auth_kind.api_key_query">API key query</option>
<option value="bearer" data-i18n="wizard.step2.auth_kind.bearer">Bearer-токен</option>
<option value="basic" data-i18n="wizard.step2.auth_kind.basic">Логин и пароль</option>
<option value="api_key_header" data-i18n="wizard.step2.auth_kind.api_key_header">API-ключ в заголовке</option>
<option value="api_key_query" data-i18n="wizard.step2.auth_kind.api_key_query">API-ключ в параметре запроса</option>
</select>
</div>
<div class="form-group" id="auth-profile-header-name-group">
<label class="form-label" data-i18n="wizard.step2.header_name">Header name</label>
<label class="form-label" data-i18n="wizard.step2.header_name">Имя заголовка</label>
<input class="form-input input-mono" id="new-auth-profile-header-name" type="text" value="Authorization" autocomplete="off" spellcheck="false">
</div>
</div>
<div class="form-group" id="auth-profile-query-param-group" hidden>
<label class="form-label" data-i18n="wizard.step2.query_param">Query param</label>
<label class="form-label" data-i18n="wizard.step2.query_param">Параметр запроса</label>
<input class="form-input input-mono" id="new-auth-profile-query-param" type="text" value="api_key" autocomplete="off" spellcheck="false">
</div>
<div class="form-row" id="auth-profile-basic-secret-row" hidden style="grid-template-columns: 1fr 1fr;">
<div class="form-group">
<label class="form-label" data-i18n="wizard.step2.username_secret">Username secret</label>
<label class="form-label" data-i18n="wizard.step2.username_secret">Секрет логина</label>
<select class="form-select" id="new-auth-profile-username-secret" data-testid="wizard-auth-username-secret-select"></select>
</div>
<div class="form-group">
<label class="form-label" data-i18n="wizard.step2.password_secret">Password secret</label>
<label class="form-label" data-i18n="wizard.step2.password_secret">Секрет пароля</label>
<select class="form-select" id="new-auth-profile-password-secret" data-testid="wizard-auth-password-secret-select"></select>
</div>
</div>
<div class="form-group" id="auth-profile-single-secret-group">
<label class="form-label" data-i18n="wizard.step2.secret_value">Secret</label>
<label class="form-label" data-i18n="wizard.step2.secret_value">Секрет</label>
<select class="form-select" id="new-auth-profile-secret-id" data-testid="wizard-auth-secret-select"></select>
</div>
<div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
<button class="btn-ghost-sm" data-testid="wizard-open-quick-secret" onclick="openQuickSecretModal(event)" data-i18n="wizard.step2.quick_secret">Quick create secret</button>
<a class="btn-ghost-sm" href="/secrets" target="_blank" rel="noopener" data-i18n="wizard.step2.manage_secrets">Open secrets page</a>
<button class="btn-ghost-sm" data-testid="wizard-open-quick-secret" onclick="openQuickSecretModal(event)" data-i18n="wizard.step2.quick_secret">Быстро создать секрет</button>
<a class="btn-ghost-sm" href="/secrets" target="_blank" rel="noopener" data-i18n="wizard.step2.manage_secrets">Открыть страницу секретов</a>
</div>
</div>
</div>
<div class="form-group">
<label class="form-label" data-i18n="wizard.step2.static_headers">Static headers (optional)</label>
<label class="form-label" data-i18n="wizard.step2.static_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>
@@ -165,11 +165,11 @@
<textarea class="form-textarea code-textarea" id="new-upstream-static-headers" rows="5">{
}</textarea>
</div>
<div class="form-hint" data-i18n="wizard.step2.static_headers_hint">Optional non-secret headers sent on every request to this upstream. Use auth profiles for credentials.</div>
<div class="form-hint" data-i18n="wizard.step2.static_headers_hint">Необязательные заголовки без секретных значений. Токены, пароли и ключи храните через профиль авторизации.</div>
</div>
<div style="display:flex; gap:8px; margin-top:4px;">
<button class="btn-primary-sm" onclick="saveNewUpstream(event)" data-i18n="wizard.step2.save_upstream">Save upstream</button>
<button class="btn-ghost-sm" onclick="cancelNewUpstream(event)" data-i18n="btn.cancel">Cancel</button>
<button class="btn-primary-sm" onclick="saveNewUpstream(event)" data-i18n="wizard.step2.save_upstream">Сохранить API-хост</button>
<button class="btn-ghost-sm" onclick="cancelNewUpstream(event)" data-i18n="btn.cancel">Отмена</button>
</div>
</div>
</div>
@@ -186,19 +186,19 @@
</svg>
</div>
<div>
<div class="config-card-title" data-i18n="wizard.step2.endpoint_title">Endpoint</div>
<div class="config-card-subtitle" data-i18n="wizard.step2.endpoint_subtitle">Path and HTTP method for this specific operation</div>
<div class="config-card-title" data-i18n="wizard.step2.endpoint_title">Путь API</div>
<div class="config-card-subtitle" data-i18n="wizard.step2.endpoint_subtitle">Путь и HTTP-метод для конкретной операции</div>
</div>
<span class="config-card-optional" style="color: var(--error, #f87171);" data-i18n="wizard.required">Required</span>
<span class="config-card-optional" style="color: var(--error, #f87171);" data-i18n="wizard.required">Обязательно</span>
</div>
<div class="config-card-body" style="gap: 16px;">
<div class="form-group">
<label class="form-label">
<span data-i18n="wizard.step2.path_template">Path template</span>
<span class="form-label-required" data-i18n="workspace_setup.required">required</span>
<span data-i18n="wizard.step2.path_template">Шаблон пути</span>
<span class="form-label-required" data-i18n="workspace_setup.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" data-i18n="wizard.step2.path_hint">Appended to the upstream base URL. Use {param} for path variables.</div>
<div class="form-hint" data-i18n="wizard.step2.path_hint">Добавляется к базовому URL API-хоста. Используйте {param} для параметров пути.</div>
</div>
</div>
</div>