Cand `rar_credentials` lipseste din cerere, submission-ul intra fara creds efemere, iar worker-ul cade pe creds-urile RAR durabile ale contului (accounts.rar_creds_enc). Identificarea contului ramane pe cheia API. Trimiterea explicita a creds-urilor suprascrie creds-urile contului pe acea cerere (back-compat: fluxul vechi ROAAUTO merge identic). - models.py: rar_credentials: RarCredentials | None = None - router.py: cripteaza creds doar daca exista (altfel creds_enc=NULL) - worker NEATINS: avea deja fallback _creds_for(...) or _creds_from_account(...) Pagina /integrare aliniata: exemplele cod (7 limbaje) + export Postman nu mai includ rar_credentials in payload; nota noua explica modelul (creds pe cont, optional in payload). README rescris compact + reflecta optionalitatea. Test nou: enqueue fara creds -> submission fara creds efemere -> fallback pe contul cu creds salvate. Suita: 673 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
350 lines
26 KiB
HTML
350 lines
26 KiB
HTML
{# Panoul Integrare: exemple de cod multi-limbaj + export & referinta. #}
|
|
{# Variabile context: account_id, base_url, exemple, are_cheie, are_creds, csrf_token #}
|
|
|
|
<div id="integrare-section">
|
|
|
|
{# Empty-state: lipsesc cheie API sau credentiale RAR #}
|
|
{% if not are_cheie or not are_creds %}
|
|
<div class="banner warn" style="margin-bottom:16px;" role="alert" aria-live="polite">
|
|
<strong>Configurare incompleta.</strong>
|
|
{% if not are_creds and not are_cheie %}
|
|
Lipsesc atat credentialele RAR cat si o cheie API activa.
|
|
{% elif not are_creds %}
|
|
Lipsesc credentialele RAR pentru trimitere.
|
|
{% else %}
|
|
Lipseste o cheie API activa.
|
|
{% endif %}
|
|
Mergi la <a href="/?tab=cont">tab-ul Cont</a> pentru a le configura.
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# Card: ID cont si endpoint de baza #}
|
|
<div class="card" style="margin-bottom:16px;">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:8px;">
|
|
<span class="muted" style="font-size:13px;">Cont ID:</span>
|
|
<strong style="font-size:13px;">{{ account_id }}</strong>
|
|
<span class="muted" style="font-size:13px; margin-left:16px;">Endpoint:</span>
|
|
<code style="font-size:12px; color:var(--accent);">{{ base_url }}</code>
|
|
</div>
|
|
<p class="muted" style="font-size:12px; margin:10px 0 0;">
|
|
Cererile trimit doar cheia API + datele prezentarii. Credentialele RAR se configureaza
|
|
o data in <a href="/?tab=cont">Cont</a> si sunt folosite automat la trimitere. Optional,
|
|
poti include <code>rar_credentials</code> in payload ca sa le suprascrii pe acea cerere.
|
|
</p>
|
|
</div>
|
|
|
|
{# Tab-list PRIMAR: limbaje #}
|
|
<div class="card" style="margin-bottom:16px;">
|
|
<div role="tablist" class="tab-bar" aria-label="Limbaje de programare" id="tl-limbaje" style="margin-bottom:0; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-curl" aria-selected="true" aria-controls="panel-curl" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer;">curl</button>
|
|
<button role="tab" id="tab-python" aria-selected="false" aria-controls="panel-python" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer;">Python</button>
|
|
<button role="tab" id="tab-php" aria-selected="false" aria-controls="panel-php" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer;">PHP</button>
|
|
<button role="tab" id="tab-csharp" aria-selected="false" aria-controls="panel-csharp" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer;">C#</button>
|
|
<button role="tab" id="tab-node" aria-selected="false" aria-controls="panel-node" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer;">Node</button>
|
|
<button role="tab" id="tab-vfp" aria-selected="false" aria-controls="panel-vfp" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer;">VFP</button>
|
|
</div>
|
|
|
|
{# Panel curl #}
|
|
<div role="tabpanel" id="panel-curl" aria-labelledby="tab-curl" style="padding:16px 0 0;">
|
|
{% set ex = exemple["curl"] %}
|
|
<div role="tablist" class="tab-bar" aria-label="Canal curl" id="tl-curl-canal" style="margin-bottom:8px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-curl-prez" aria-selected="true" aria-controls="panel-curl-prez" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:13px;">Prezentari JSON</button>
|
|
<button role="tab" id="tab-curl-import" aria-selected="false" aria-controls="panel-curl-import" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:13px;">Import fisier</button>
|
|
</div>
|
|
<div role="tabpanel" id="panel-curl-prez" aria-labelledby="tab-curl-prez">
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet curl prezentari" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["prezentari"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
<div role="tabpanel" id="panel-curl-import" aria-labelledby="tab-curl-import" hidden>
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet curl import" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["import"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{# Panel python #}
|
|
<div role="tabpanel" id="panel-python" aria-labelledby="tab-python" hidden style="padding:16px 0 0;">
|
|
{% set ex = exemple["python"] %}
|
|
<div role="tablist" class="tab-bar" aria-label="Canal python" id="tl-python-canal" style="margin-bottom:8px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-python-prez" aria-selected="true" aria-controls="panel-python-prez" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:13px;">Prezentari JSON</button>
|
|
<button role="tab" id="tab-python-import" aria-selected="false" aria-controls="panel-python-import" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:13px;">Import fisier</button>
|
|
</div>
|
|
<div role="tabpanel" id="panel-python-prez" aria-labelledby="tab-python-prez">
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet python prezentari" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["prezentari"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
<div role="tabpanel" id="panel-python-import" aria-labelledby="tab-python-import" hidden>
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet python import" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["import"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{# Panel PHP #}
|
|
<div role="tabpanel" id="panel-php" aria-labelledby="tab-php" hidden style="padding:16px 0 0;">
|
|
{% set ex = exemple["php"] %}
|
|
<div role="tablist" class="tab-bar" aria-label="Canal php" id="tl-php-canal" style="margin-bottom:8px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-php-prez" aria-selected="true" aria-controls="panel-php-prez" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:13px;">Prezentari JSON</button>
|
|
<button role="tab" id="tab-php-import" aria-selected="false" aria-controls="panel-php-import" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:13px;">Import fisier</button>
|
|
</div>
|
|
<div role="tabpanel" id="panel-php-prez" aria-labelledby="tab-php-prez">
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet php prezentari" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["prezentari"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
<div role="tabpanel" id="panel-php-import" aria-labelledby="tab-php-import" hidden>
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet php import" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["import"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{# Panel C# #}
|
|
<div role="tabpanel" id="panel-csharp" aria-labelledby="tab-csharp" hidden style="padding:16px 0 0;">
|
|
{% set ex = exemple["csharp"] %}
|
|
<div role="tablist" class="tab-bar" aria-label="Canal csharp" id="tl-csharp-canal" style="margin-bottom:8px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-csharp-prez" aria-selected="true" aria-controls="panel-csharp-prez" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:13px;">Prezentari JSON</button>
|
|
<button role="tab" id="tab-csharp-import" aria-selected="false" aria-controls="panel-csharp-import" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:13px;">Import fisier</button>
|
|
</div>
|
|
<div role="tabpanel" id="panel-csharp-prez" aria-labelledby="tab-csharp-prez">
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet csharp prezentari" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["prezentari"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
<div role="tabpanel" id="panel-csharp-import" aria-labelledby="tab-csharp-import" hidden>
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet csharp import" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["import"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{# Panel Node #}
|
|
<div role="tabpanel" id="panel-node" aria-labelledby="tab-node" hidden style="padding:16px 0 0;">
|
|
{% set ex = exemple["node"] %}
|
|
<div role="tablist" class="tab-bar" aria-label="Canal node" id="tl-node-canal" style="margin-bottom:8px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-node-prez" aria-selected="true" aria-controls="panel-node-prez" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:13px;">Prezentari JSON</button>
|
|
<button role="tab" id="tab-node-import" aria-selected="false" aria-controls="panel-node-import" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:13px;">Import fisier</button>
|
|
</div>
|
|
<div role="tabpanel" id="panel-node-prez" aria-labelledby="tab-node-prez">
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet node prezentari" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["prezentari"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
<div role="tabpanel" id="panel-node-import" aria-labelledby="tab-node-import" hidden>
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet node import" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["import"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{# Panel VFP: tab-list SECUNDAR pentru dialecte #}
|
|
<div role="tabpanel" id="panel-vfp" aria-labelledby="tab-vfp" hidden style="padding:16px 0 0;">
|
|
<p class="muted" style="font-size:13px; margin:0 0 8px;">Visual FoxPro — alege dialectul COM:</p>
|
|
{# Dialecte VFP #}
|
|
<div role="tablist" class="tab-bar" aria-label="Dialecte VFP" id="tl-vfp-dialect" style="margin-bottom:12px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-vfp-msxml" aria-selected="true" aria-controls="panel-vfp-msxml" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:13px;">MSXML2</button>
|
|
<button role="tab" id="tab-vfp-winhttp" aria-selected="false" aria-controls="panel-vfp-winhttp" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:13px;">WinHttp</button>
|
|
</div>
|
|
|
|
{# MSXML2 #}
|
|
<div role="tabpanel" id="panel-vfp-msxml" aria-labelledby="tab-vfp-msxml">
|
|
{% set ex = exemple["vfp_msxml"] %}
|
|
<div role="tablist" class="tab-bar" aria-label="Canal vfp msxml" id="tl-vfp-msxml-canal" style="margin-bottom:8px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-vfp-msxml-prez" aria-selected="true" aria-controls="panel-vfp-msxml-prez" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:12px;">Prezentari JSON</button>
|
|
<button role="tab" id="tab-vfp-msxml-import" aria-selected="false" aria-controls="panel-vfp-msxml-import" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:12px;">Import fisier</button>
|
|
</div>
|
|
<div role="tabpanel" id="panel-vfp-msxml-prez" aria-labelledby="tab-vfp-msxml-prez">
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet VFP MSXML2 prezentari" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["prezentari"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
<div role="tabpanel" id="panel-vfp-msxml-import" aria-labelledby="tab-vfp-msxml-import" hidden>
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet VFP MSXML2 import" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["import"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
</div>
|
|
|
|
{# WinHttp #}
|
|
<div role="tabpanel" id="panel-vfp-winhttp" aria-labelledby="tab-vfp-winhttp" hidden>
|
|
{% set ex = exemple["vfp_winhttp"] %}
|
|
<div role="tablist" class="tab-bar" aria-label="Canal vfp winhttp" id="tl-vfp-winhttp-canal" style="margin-bottom:8px; border-bottom:1px solid var(--line);">
|
|
<button role="tab" id="tab-vfp-winhttp-prez" aria-selected="true" aria-controls="panel-vfp-winhttp-prez" tabindex="0" class="tab-link tab-activ" style="border:none; background:none; cursor:pointer; font-size:12px;">Prezentari JSON</button>
|
|
<button role="tab" id="tab-vfp-winhttp-import" aria-selected="false" aria-controls="panel-vfp-winhttp-import" tabindex="-1" class="tab-link" style="border:none; background:none; cursor:pointer; font-size:12px;">Import fisier</button>
|
|
</div>
|
|
<div role="tabpanel" id="panel-vfp-winhttp-prez" aria-labelledby="tab-vfp-winhttp-prez">
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet VFP WinHttp prezentari" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["prezentari"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
<div role="tabpanel" id="panel-vfp-winhttp-import" aria-labelledby="tab-vfp-winhttp-import" hidden>
|
|
<div style="position:relative;">
|
|
<button class="btn-copiaza" aria-label="Copiaza snippet VFP WinHttp import" style="position:absolute; top:8px; right:8px; font-size:12px; padding:4px 10px; background:var(--line); color:var(--ink); border:1px solid var(--line); border-radius:4px; cursor:pointer;">Copiaza</button>
|
|
<pre style="background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:16px; overflow-x:auto; margin:0;"><code style="font-size:12px; font-family:ui-monospace,monospace; color:var(--ink);">{{ ex["import"] | e }}</code></pre>
|
|
</div>
|
|
<div aria-live="polite" class="copiaza-feedback muted" style="font-size:12px; min-height:20px; margin-top:4px;"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# Card: Export & referinta #}
|
|
<div class="card" style="margin-bottom:16px;">
|
|
<h3 style="margin:0 0 12px; font-size:15px;">Export & referinta</h3>
|
|
<div style="display:flex; flex-wrap:wrap; gap:8px;">
|
|
<a class="cardlink" href="/docs" target="_blank" rel="noopener">Swagger UI — /docs</a>
|
|
<a class="cardlink" href="/openapi.json" target="_blank" rel="noopener">Schema OpenAPI — /openapi.json</a>
|
|
<a class="cardlink" href="/v1/integrare/postman.json" download>Colectie Postman — /v1/integrare/postman.json</a>
|
|
</div>
|
|
</div>
|
|
|
|
{# Formular test conexiune #}
|
|
<div class="card" style="margin-bottom:16px;">
|
|
<h3 style="margin:0 0 12px; font-size:15px;">Testeaza conexiunea</h3>
|
|
<form hx-post="/integrare/test-cheie"
|
|
hx-target="#integrare-test-rezultat"
|
|
hx-swap="innerHTML"
|
|
style="display:flex; gap:8px; flex-wrap:wrap; align-items:flex-end;">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
<div>
|
|
<label for="test-api-key" style="display:block; font-size:13px; color:var(--muted); margin-bottom:4px;">Cheie API (rfak_...)</label>
|
|
<input type="password" id="test-api-key" name="api_key" placeholder="rfak_..."
|
|
style="width:280px;" autocomplete="off">
|
|
<p class="muted" style="font-size:12px; margin:4px 0 0;">Verificam doar daca cheia e valida. Nu o salvam si nu o memoram — cheia se gestioneaza in Cont.</p>
|
|
</div>
|
|
<button type="submit">Testeaza</button>
|
|
</form>
|
|
<div id="integrare-test-rezultat" style="margin-top:8px;"></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
(function() {
|
|
/* Navigare ARIA pentru tab-uri multiple (scoped pe containerul propriu). */
|
|
var root = document.getElementById('integrare-section');
|
|
if (!root) return;
|
|
root.querySelectorAll('[role="tablist"]').forEach(function(tablist) {
|
|
var tabs = Array.from(tablist.querySelectorAll('[role="tab"]'));
|
|
if (!tabs.length) return;
|
|
|
|
/* Navigare cu sageti, Home, End */
|
|
tablist.addEventListener('keydown', function(e) {
|
|
var idx = tabs.indexOf(document.activeElement);
|
|
if (idx === -1) return;
|
|
var next = -1;
|
|
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
|
|
next = (idx + 1) % tabs.length;
|
|
} else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
|
|
next = (idx - 1 + tabs.length) % tabs.length;
|
|
} else if (e.key === 'Home') {
|
|
next = 0;
|
|
} else if (e.key === 'End') {
|
|
next = tabs.length - 1;
|
|
}
|
|
if (next !== -1) {
|
|
e.preventDefault();
|
|
tabs[next].focus();
|
|
}
|
|
});
|
|
|
|
/* Click pe tab: activeaza panelul corespunzator */
|
|
tabs.forEach(function(tab) {
|
|
tab.addEventListener('click', function() {
|
|
var panelId = tab.getAttribute('aria-controls');
|
|
if (!panelId) return;
|
|
/* Dezactiveaza toate tab-urile din acest tablist */
|
|
tabs.forEach(function(t) {
|
|
t.setAttribute('aria-selected', 'false');
|
|
t.setAttribute('tabindex', '-1');
|
|
t.classList.remove('tab-activ');
|
|
var pid = t.getAttribute('aria-controls');
|
|
if (pid) {
|
|
var p = document.getElementById(pid);
|
|
if (p) p.hidden = true;
|
|
}
|
|
});
|
|
/* Activeaza tab-ul curent */
|
|
tab.setAttribute('aria-selected', 'true');
|
|
tab.setAttribute('tabindex', '0');
|
|
tab.classList.add('tab-activ');
|
|
var panel = document.getElementById(panelId);
|
|
if (panel) panel.hidden = false;
|
|
});
|
|
});
|
|
});
|
|
|
|
/* Buton Copiaza: citeste textul din <pre><code> sibling, nu din data-* */
|
|
root.querySelectorAll('.btn-copiaza').forEach(function(btn) {
|
|
btn.addEventListener('click', function() {
|
|
var wrapper = btn.closest('div[style*="position:relative"]') || btn.parentElement;
|
|
var code = wrapper ? wrapper.querySelector('pre code') : null;
|
|
if (!code) return;
|
|
var text = code.innerText || code.textContent;
|
|
var feedback = wrapper.parentElement && wrapper.parentElement.querySelector('.copiaza-feedback');
|
|
|
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
navigator.clipboard.writeText(text).then(function() {
|
|
btn.textContent = 'Copiat';
|
|
setTimeout(function() { btn.textContent = 'Copiaza'; }, 2000);
|
|
if (feedback) {
|
|
feedback.textContent = 'Copiat!';
|
|
setTimeout(function() { feedback.textContent = ''; }, 2000);
|
|
}
|
|
}).catch(function() {
|
|
if (feedback) feedback.textContent = 'Eroare la copiere.';
|
|
});
|
|
} else {
|
|
/* Fallback pentru browsere fara Clipboard API */
|
|
var ta = document.createElement('textarea');
|
|
ta.value = text;
|
|
ta.style.position = 'fixed';
|
|
ta.style.opacity = '0';
|
|
document.body.appendChild(ta);
|
|
ta.select();
|
|
try {
|
|
document.execCommand('copy');
|
|
btn.textContent = 'Copiat';
|
|
setTimeout(function() { btn.textContent = 'Copiaza'; }, 2000);
|
|
if (feedback) {
|
|
feedback.textContent = 'Copiat!';
|
|
setTimeout(function() { feedback.textContent = ''; }, 2000);
|
|
}
|
|
} catch(err) {
|
|
if (feedback) feedback.textContent = 'Eroare la copiere.';
|
|
}
|
|
document.body.removeChild(ta);
|
|
}
|
|
});
|
|
});
|
|
})();
|
|
</script>
|