ff68b0b433
gates / gates (push) Successful in 20s
Ten pages converted against fixtures captured from unconverted templates (6be55a0); marker
coverage test; English page mask narrowed; English retrieval-promise stems; common keys;
title keys and infraMeta from the bundle; old wording tests read the Hungarian expansion.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
147 lines
7.4 KiB
HTML
147 lines
7.4 KiB
HTML
{{define "launch_tile"}}
|
|
<span class="launch-tile{{if .Off}} launch-tile--off{{end}}" style="background: {{tileColor .Slug .BrandColor}}">
|
|
<span class="launch-mono">{{initial .DisplayName}}</span>
|
|
<img class="launch-logo" src="{{logoURL .Slug}}" alt=""
|
|
onerror="if(!this.dataset.step){this.dataset.step='1';this.src='{{logoPNGURL .Slug}}';}else{this.onerror=null;this.style.display='none';this.parentElement.classList.add('launch-tile--noimg');}">
|
|
</span>
|
|
{{end}}
|
|
|
|
{{define "launcher"}}
|
|
{{template "layout_start" .}}
|
|
|
|
<div class="page-header">
|
|
<h2>{{T "launcher.inditopult"}}</h2>
|
|
<span class="domain-badge">{{.Domain}}</span>
|
|
<button type="button" class="btn btn-outline share-open-btn" onclick="openShareModal()"><svg class="ico"><use href="#i-share"/></svg>{{T "launcher.inditopult_megosztasa"}}</button>
|
|
</div>
|
|
|
|
{{if .ShareFlash}}
|
|
<div class="alerts-container">
|
|
<div class="alert-banner alert-banner-info">
|
|
<span class="alert-icon"><svg class="ico"><use href="#i-info"/></svg></span>
|
|
<span class="alert-message">{{.ShareFlash}}</span>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{if .Apps}}
|
|
<div class="launch-grid">
|
|
{{range .Apps}}
|
|
{{if isOperational .State}}
|
|
<a class="launch-cell" href="https://{{.Subdomain}}.{{$.Domain}}{{.OpenPath}}" target="_blank" rel="noopener">
|
|
{{template "launch_tile" (dict "Slug" .Slug "BrandColor" .BrandColor "DisplayName" .DisplayName "Off" false)}}
|
|
<span class="launch-name">{{.DisplayName}}</span>
|
|
{{if ne (stateStr .State) "running"}}<span class="tag tag-{{stateColor .State}}"><span class="dot"></span>{{stateLabel .State}}</span>{{end}}
|
|
</a>
|
|
{{else}}
|
|
<div class="launch-cell launch-cell--off">
|
|
{{template "launch_tile" (dict "Slug" .Slug "BrandColor" .BrandColor "DisplayName" .DisplayName "Off" true)}}
|
|
<span class="launch-name">{{.DisplayName}}</span>
|
|
<span class="tag tag-{{stateColor .State}}"><span class="dot"></span>{{stateLabel .State}}</span>
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
</div>
|
|
{{else}}
|
|
<div class="empty-state">
|
|
<p>{{T "launcher.meg_nincs_telepitett_alkalmazas"}}</p>
|
|
<p><a href="/stacks" class="empty-state-link">{{T "launcher.alkalmazasok_telepitese"}}</a></p>
|
|
</div>
|
|
{{end}}
|
|
|
|
<div class="modal-overlay" id="share-modal" style="display:none">
|
|
<div class="modal-card">
|
|
<h3>{{T "launcher.inditopult_megosztasa"}}</h3>
|
|
<p class="share-lede">{{T "launcher.egy_megoszthato_link_amely_csak"}}</p>
|
|
{{if .ShareEnabled}}
|
|
<div class="share-field">
|
|
<label class="share-label">{{T "launcher.megosztasi_link"}}</label>
|
|
<div class="share-link-row">
|
|
<input id="share-link-input" type="text" readonly value="{{.ShareURL}}">
|
|
<button type="button" id="share-copy-btn" class="btn btn-outline" onclick="copyShareLink()">{{T "launcher.link_masolasa"}}</button>
|
|
<button type="button" id="share-native-btn" class="btn btn-outline" style="display:none" onclick="nativeShare()">{{T "launcher.megosztas"}}</button>
|
|
</div>
|
|
</div>
|
|
<div class="share-qr">
|
|
<img src="/launcher/share/qr.png" alt="{{T "launcher.qr_kod_a_megosztasi_linkhez"}}" width="200" height="200">
|
|
<span class="share-qr-hint">{{T "launcher.olvassa_be_telefonnal_a_gyors"}}</span>
|
|
</div>
|
|
<div class="share-field">
|
|
{{if .SharePasswordSet}}
|
|
<label class="share-label">{{T "common.jelszo"}}</label>
|
|
<p class="share-note">{{T "launcher.a_megosztas_jelszoval_vedett"}}</p>
|
|
<form method="POST" action="/launcher/share/password">
|
|
{{.CSRFField}}
|
|
<input type="hidden" name="action" value="clear">
|
|
<button type="submit" class="btn btn-outline">{{T "launcher.jelszo_torlese"}}</button>
|
|
</form>
|
|
{{else}}
|
|
<form method="POST" action="/launcher/share/password">
|
|
{{.CSRFField}}
|
|
<label class="share-label">{{T "launcher.jelszo_nem_kotelezo"}}</label>
|
|
<div class="share-link-row">
|
|
<input type="password" name="password" autocomplete="new-password" placeholder="{{T "launcher.legalabb_8_karakter"}}">
|
|
<button type="submit" class="btn btn-outline">{{T "launcher.jelszo_beallitasa"}}</button>
|
|
</div>
|
|
</form>
|
|
{{end}}
|
|
</div>
|
|
<div class="share-actions">
|
|
<form method="POST" action="/launcher/share/rotate">
|
|
{{.CSRFField}}
|
|
<button type="submit" class="btn btn-outline" data-confirm="{{T "launcher.uj_link_keszitese_a_regi"}}">{{T "launcher.uj_link_keszitese"}}</button>
|
|
</form>
|
|
<form method="POST" action="/launcher/share/disable">
|
|
{{.CSRFField}}
|
|
<button type="submit" class="btn btn-danger" data-confirm="{{T "launcher.biztosan_kikapcsolja_a_megosztast_a"}}">{{T "launcher.megosztas_kikapcsolasa"}}</button>
|
|
</form>
|
|
</div>
|
|
{{else}}
|
|
<p class="share-note">{{T "launcher.a_megosztas_jelenleg_ki_van"}}</p>
|
|
<form method="POST" action="/launcher/share/enable">
|
|
{{.CSRFField}}
|
|
<div class="modal-actions">
|
|
<button type="button" class="btn btn-outline" onclick="closeShareModal()">{{T "common.bezaras"}}</button>
|
|
<button type="submit" class="btn btn-primary">{{T "launcher.megosztas_bekapcsolasa"}}</button>
|
|
</div>
|
|
</form>
|
|
{{end}}
|
|
{{if .ShareEnabled}}
|
|
<div class="modal-actions">
|
|
<button type="button" class="btn btn-outline" onclick="closeShareModal()">{{T "common.bezaras"}}</button>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function openShareModal(){var m=document.getElementById('share-modal');if(m)m.style.display='flex';}
|
|
function closeShareModal(){var m=document.getElementById('share-modal');if(m)m.style.display='none';}
|
|
function copyShareLink(){
|
|
var inp=document.getElementById('share-link-input');
|
|
var btn=document.getElementById('share-copy-btn');
|
|
if(!inp)return;
|
|
function done(){if(btn){var o=btn.textContent;btn.textContent='{{T "launcher.masolva"}}';setTimeout(function(){btn.textContent=o;},1500);}}
|
|
if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(inp.value).then(done,function(){inp.select();done();});}
|
|
else{inp.select();try{document.execCommand('copy');}catch(e){}done();}
|
|
}
|
|
// Native OS share sheet (Web Share API, feature-detected). URL + title/text only — never the QR as a
|
|
// file: file-share support is narrow and several targets drop the URL when handed file+URL. On a
|
|
// non-cancel rejection, fall back to the universal clipboard copy so the user still keeps the link.
|
|
function nativeShare(){
|
|
var inp=document.getElementById('share-link-input');
|
|
if(!inp||!navigator.share)return;
|
|
navigator.share({title:'{{T "launcher.inditopult_2"}}',text:'{{T "launcher.az_otthoni_alkalmazasok_egy_helyen"}}',url:inp.value})
|
|
.catch(function(e){if(e&&e.name==='AbortError')return;copyShareLink();});
|
|
}
|
|
(function(){
|
|
var m=document.getElementById('share-modal');
|
|
if(m){m.addEventListener('click',function(e){if(e.target===m)closeShareModal();});}
|
|
if(navigator.share){var nb=document.getElementById('share-native-btn');if(nb)nb.style.display='';}
|
|
{{if .ShareFlash}}openShareModal();{{end}}
|
|
})();
|
|
</script>
|
|
|
|
{{template "layout_end"}}
|
|
{{end}}
|