feat(OQ-30): browser-panel + /docs/ proxy-fetch i opax.html
This commit is contained in:
parent
8f0829f6b3
commit
7bd1d3fb50
|
|
@ -283,6 +283,17 @@
|
|||
.roi-sub{font-size:12px;color:var(--text-dim);margin-top:4px;line-height:1.5}
|
||||
.roi-divider{width:1px;height:60px;background:var(--border);flex-shrink:0}
|
||||
@media(max-width:600px){.roi-divider{display:none}.roi-box{gap:16px}}
|
||||
|
||||
/* BROWSER PANEL */
|
||||
.browser-bar{display:flex;align-items:center;gap:8px;padding:10px 16px;border-bottom:1px solid var(--border);background:var(--bg-2);flex-shrink:0}
|
||||
.browser-url-input{flex:1;background:var(--bg-3);border:1px solid var(--border);border-radius:8px;padding:6px 12px;font-family:var(--mono);font-size:12px;color:var(--text);outline:none;transition:border-color .2s}
|
||||
.browser-url-input:focus{border-color:var(--accent)}
|
||||
.browser-url-input::placeholder{color:var(--text-faint)}
|
||||
.browser-go-btn{padding:6px 14px;border-radius:8px;background:var(--accent);color:#fff;font-size:12px;font-weight:600;transition:background .14s;white-space:nowrap}
|
||||
.browser-go-btn:hover{background:#6a4cff}
|
||||
.browser-frame{flex:1;border:none;width:100%;height:100%;background:var(--bg)}
|
||||
.browser-error{display:none;flex:1;align-items:center;justify-content:center;flex-direction:column;gap:12px;color:var(--text-faint);font-family:var(--mono);font-size:13px}
|
||||
.browser-error.show{display:flex}
|
||||
</style>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
|
||||
</head>
|
||||
|
|
@ -332,6 +343,9 @@
|
|||
<div class="nav-item" onclick="go('md')" id="nav-md">
|
||||
<span class="nav-icon">📄</span> MD
|
||||
</div>
|
||||
<div class="nav-item" onclick="go('browser')" id="nav-browser">
|
||||
<span class="nav-icon">🌐</span> Browser
|
||||
</div>
|
||||
|
||||
<div class="side-foot">
|
||||
<div class="me-card">
|
||||
|
|
@ -565,6 +579,30 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- BROWSER -->
|
||||
<div class="panel" id="panel-browser">
|
||||
<div class="panel-head">
|
||||
<div class="p-avatar" style="background:linear-gradient(135deg,#5c8fff,#7c5cff)">🌐</div>
|
||||
<div>
|
||||
<div class="p-title">Browser</div>
|
||||
<div class="p-sub">Intern dokumentasjonsleser · /docs/ proxy</div>
|
||||
</div>
|
||||
<div class="p-actions">
|
||||
<button class="hbtn" onclick="browserRefresh()">↻ Refresh</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="browser-bar">
|
||||
<input id="browser-url" class="browser-url-input" type="text" placeholder="https://... eller /docs/MASTERPLAN.md" onkeydown="if(event.key==='Enter')browserNav()">
|
||||
<button class="browser-go-btn" onclick="browserNav()">Gå →</button>
|
||||
</div>
|
||||
<div id="browser-error" class="browser-error">
|
||||
<span style="font-size:32px">⚠️</span>
|
||||
<span id="browser-error-msg">Kunne ikke laste siden</span>
|
||||
</div>
|
||||
<iframe id="browser-frame" class="browser-frame" src="" sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
|
||||
onload="browserFrameLoad()" onerror="browserFrameError()"></iframe>
|
||||
</div>
|
||||
|
||||
</div><!-- /panels -->
|
||||
</div><!-- /main -->
|
||||
</div><!-- /shell -->
|
||||
|
|
@ -575,7 +613,6 @@ const AGENT_URL = ''
|
|||
const USER_ID = 'chris'
|
||||
const STORAGE_KEY = 'jason_history_v2'
|
||||
const SESSION_KEY = 'jason_session_v2'
|
||||
const GH_RAW = 'https://raw.githubusercontent.com/vauco-saas/OSVauco/main/'
|
||||
const GH_BLOB = 'https://github.com/vauco-saas/OSVauco/blob/main/'
|
||||
|
||||
const MD_DOCS = [
|
||||
|
|
@ -598,6 +635,7 @@ const PANEL_META = {
|
|||
sites: ['Sites & Moduler', 'Alle Vauco-flater'],
|
||||
terminal: ['Terminal', 'OPAX agent · Cloud Run'],
|
||||
md: ['MD — Dokumenter', 'Kjerndoks · vauco-saas/OSVauco'],
|
||||
browser: ['Browser', 'Intern dokumentasjonsleser · /docs/ proxy'],
|
||||
}
|
||||
|
||||
const SITES_DATA = [
|
||||
|
|
@ -648,7 +686,6 @@ function updatePricing(val){
|
|||
|
||||
renderTierGrid(spend)
|
||||
|
||||
// ROI: 15% of spend saved via CostGuard optimisation
|
||||
const savings = spend * 0.15
|
||||
const net_monthly = savings - tier.price
|
||||
const net_annual = net_monthly * 12
|
||||
|
|
@ -706,6 +743,26 @@ function initPricing(){
|
|||
updatePricing(slider.value)
|
||||
}
|
||||
|
||||
// BROWSER PANEL
|
||||
function browserNav(){
|
||||
const raw = document.getElementById('browser-url').value.trim()
|
||||
if(!raw) return
|
||||
const url = raw.startsWith('http') ? raw : '/docs/'+raw.replace(/^\/docs\//,'')
|
||||
document.getElementById('browser-error').classList.remove('show')
|
||||
document.getElementById('browser-frame').src = url
|
||||
}
|
||||
function browserRefresh(){
|
||||
const f = document.getElementById('browser-frame')
|
||||
if(f.src) f.src = f.src
|
||||
}
|
||||
function browserFrameLoad(){
|
||||
document.getElementById('browser-error').classList.remove('show')
|
||||
}
|
||||
function browserFrameError(){
|
||||
document.getElementById('browser-error-msg').textContent = 'Siden kunne ikke lastes — sjekk URL eller /docs/-proxy'
|
||||
document.getElementById('browser-error').classList.add('show')
|
||||
}
|
||||
|
||||
// BUILD STATUS POLL
|
||||
async function pollBuild(){
|
||||
try{
|
||||
|
|
@ -893,7 +950,10 @@ async function openMd(path, name){
|
|||
const viewer=document.getElementById('md-viewer')
|
||||
viewer.innerHTML='<div class="md-viewer-loading"><span style="animation:pulse 1s infinite">⏳</span> Laster '+esc(path)+'...</div>'
|
||||
try{
|
||||
const raw=await fetch(GH_RAW+path+'?t='+Date.now()).then(r=>{ if(!r.ok) throw new Error('HTTP '+r.status); return r.text() })
|
||||
// OQ-30: bruk /docs/ proxy i stedet for GH_RAW
|
||||
const res = await fetch('/docs/'+path+'?t='+Date.now())
|
||||
if(!res.ok) throw new Error('HTTP '+res.status)
|
||||
const raw = await res.text()
|
||||
viewer.innerHTML=renderMd(raw)
|
||||
}catch(e){
|
||||
viewer.innerHTML=`<div class="md-viewer-loading">❌ Kunne ikke laste: ${esc(e.message)}</div>`
|
||||
|
|
@ -1047,7 +1107,6 @@ function exportHistory(){
|
|||
}
|
||||
;(function(){ const h=lh();if(!h.length)return;h.forEach(m=>appendMsg(m.role,m.text,m.ts));document.getElementById('messages').scrollTop=99999 })()
|
||||
inp.focus()
|
||||
// Init pricing on load so slider is ready if user navigates directly
|
||||
renderTierGrid(5000)
|
||||
updatePricing(5000)
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user