Files
adlist_mikrotik/templates/form.html
T
2026-10-09 10:53:10 +02:00

112 lines
7.8 KiB
HTML

{% extends 'base.html' %}
{% set page = 'converter' %}
{% block title %}Converter{% endblock %}
{% block content %}
<section class="page-intro">
<div>
<div class="eyebrow"><i class="signal" aria-hidden="true"></i> THE CONVERSION WORKSPACE</div>
<h1>Blocklists, <em>made compatible.</em></h1>
<p class="lead">Turn public hosts, DNS and adblock sources into MikroTik-compatible lists. One source URL. One output link. Ready for your DNS setup.</p>
</div>
<div class="hero-identity" aria-hidden="true"><span>DNS</span><span class="hero-line"></span><strong>LIST</strong><small>/CONVERT</small></div>
</section>
<section class="workspace-grid" aria-label="Conversion tools">
<article class="card generator-card" id="generator">
<header class="card-heading">
<div><span class="small-label">01 / CONFIGURATION</span><h2>Link generator</h2></div>
<span class="pill live"><i class="signal" aria-hidden="true"></i> READY</span>
</header>
<form id="converter-form" novalidate>
<div class="field">
<label for="url-input">Source URL <span class="required">*</span></label>
<div class="input-wrap url-field">
<span class="input-prefix" aria-hidden="true">↗</span>
<input type="url" id="url-input" name="url" placeholder="https://example.com/blocklist.txt" inputmode="url" autocomplete="url" spellcheck="false" aria-describedby="url-help url-error" required>
</div>
<div class="field-hint" id="url-help">Paste a direct link to a plain-text hosts or adblock list.</div>
<p class="field-error" id="url-error" role="alert" hidden></p>
</div>
<div class="field">
<div class="label-row"><label for="ip-input">Target IP <span class="required">*</span></label><span class="fine">IPv4 / IPv6 supported</span></div>
<div class="preset-row" role="group" aria-label="Target IP presets">
<button type="button" class="preset" data-ip="0.0.0.0">0.0.0.0 <small>BLACKHOLE</small></button>
<button type="button" class="preset" data-ip="127.0.0.1">127.0.0.1 <small>LOOPBACK</small></button>
<button type="button" class="preset" data-ip="195.187.6.34">195.187.6.34 <small>DEFAULT</small></button>
</div>
<input id="ip-input" name="ip" type="text" value="195.187.6.34" inputmode="text" autocomplete="off" spellcheck="false" aria-describedby="ip-error" required>
<p class="field-error" id="ip-error" role="alert" hidden></p>
</div>
<div class="form-controls">
<div class="form-status"><i class="signal" aria-hidden="true"></i><span id="validation-status">Waiting for a source URL</span></div>
<button type="button" class="quiet" data-action="clear">Reset fields</button>
</div>
</form>
</article>
<aside class="side-column">
<section class="card guide-card" id="guide">
<div class="card-heading"><div><span class="small-label">02 / WORKFLOW</span><h2>How it works</h2></div></div>
<div class="workflow-step"><span class="step-num">01</span><div><strong>Choose a source</strong><p>Add a public URL to a supported list.</p></div></div>
<div class="workflow-step"><span class="step-num">02</span><div><strong>Set your target</strong><p>Select the IP used for blocked domains.</p></div></div>
<div class="workflow-step"><span class="step-num">03</span><div><strong>Copy and deploy</strong><p>Use the generated address in IP → DNS → Adlist.</p></div></div>
</section>
<section class="card support-card">
<header class="card-heading"><div><span class="small-label">INPUT / COMPATIBILITY</span><h2>Supported formats</h2></div><span class="pill">TEXT</span></header>
<div class="format-list"><span>Hosts</span><span>AdGuard / uBlock</span><span>dnsmasq</span><span>Plain domains</span></div>
<p class="fine">The source is checked before the response is delivered. Invalid lists return an English error page.</p>
</section>
</aside>
</section>
<section class="card result-card" id="result" aria-labelledby="result-heading">
<header class="card-heading">
<div><span class="small-label">03 / GENERATED OUTPUT</span><h2 id="result-heading">Your conversion endpoint</h2></div>
<span class="pill" id="link-state">AWAITING INPUT</span>
</header>
<p class="fine result-intro">The link updates as you type. Generating the address does not download the source; conversion runs when the endpoint is requested.</p>
<div class="output-row">
<div class="output-field"><span class="output-mark">GET</span><input id="generated-link" type="text" readonly aria-label="Generated conversion link" placeholder="Enter a valid source URL to generate your link"></div>
<div class="output-actions">
<button type="button" class="primary" data-action="copy" data-target="#generated-link" id="copy-btn" disabled>
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><rect x="8" y="8" width="12" height="12" rx="1"/><path d="M16 8V4H4v12h4"/></svg> Copy link
</button>
<a class="outline" id="open-link" href="#" target="_blank" rel="noopener noreferrer" aria-disabled="true" tabindex="-1">Open <span aria-hidden="true">↗</span></a>
</div>
</div>
<div class="result-footer"><span class="success-note"><i class="signal" aria-hidden="true"></i> VALID RESULTS ARE CACHEABLE</span><span>Shared cache: up to {{ cache_days }} days (proxy configuration required)</span></div>
</section>
<section class="card recent-card" id="recent-links" aria-labelledby="recent-heading">
<header class="card-heading card-heading-responsive">
<div><span class="small-label">04 / RECENT ACTIVITY</span><h2 id="recent-heading">Recently converted sources <span class="count">{{ recent_links|length }}</span></h2></div>
<div class="head-actions"><label class="sr-only" for="recent-filter">Filter recent sources</label><input id="recent-filter" type="search" placeholder="Search sources or IPs…" data-filter="#recent-table" autocomplete="off"></div>
</header>
<div class="table-scroll">
<table class="data-table" id="recent-table">
<thead><tr><th>Source</th><th>Target IP</th><th>Last used</th><th class="actions-cell">Actions</th></tr></thead>
<tbody>
{% for item in recent_links %}
<tr {% if loop.index > 8 %}hidden data-extra-row="true"{% endif %}>
<td class="source-cell"><span class="source-glyph" aria-hidden="true">↗</span><a href="{{ url_for('convert',url=item[1],ip=item[2]) }}" target="_blank" rel="noopener noreferrer" title="{{ item[1] }}">{{ item[1] }}</a></td>
<td class="mono"><span class="ip-label">{{ item[2] }}</span></td>
<td class="mono subdued nowrap">{{ item[0]|datetimeformat }}</td>
<td class="row-actions">
<button type="button" class="quiet tiny" data-action="use-source" data-url="{{ item[1] }}" data-ip="{{ item[2] }}">Use</button>
<button type="button" class="quiet tiny" data-action="copy-text" data-text="{{ url_for('convert', url=item[1], ip=item[2]) }}">Copy</button>
<a class="quiet tiny" href="{{ url_for('convert',url=item[1],ip=item[2]) }}" target="_blank" rel="noopener noreferrer">Open ↗</a>
</td>
</tr>
{% else %}
<tr class="empty-row"><td colspan="4" class="empty-table"><span class="empty-title">No recent links yet</span><span>Successful conversions will appear here.</span></td></tr>
{% endfor %}
</tbody>
</table>
</div>
{% if recent_links|length > 8 %}
<div class="table-footer"><span class="fine">Showing 8 of {{ recent_links|length }} entries</span><button class="quiet tiny" type="button" data-action="show-all" data-target="#recent-table">Show all entries ↓</button></div>
{% endif %}
<p class="fine no-results" id="recent-empty" hidden>No entries match this search.</p>
</section>
{% endblock %}