Merge claude/2
This commit is contained in:
commit
431d6561a8
@ -25,20 +25,21 @@ class CatalogManager {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// The pinned official row (source #1). URL comes from the generated catalog
|
||||
// data; the hidden CFG_CATALOG_OFFICIAL_ENABLED input carries its on/off state
|
||||
// so it saves with the rest on "Save Config".
|
||||
// The pinned official row (source #1). Renders the official URL in a read-only
|
||||
// input — same element (and height) as the third-party rows — with the badge
|
||||
// overlaid. The hidden CFG_CATALOG_OFFICIAL_ENABLED input carries its on/off
|
||||
// state so it saves with the rest on "Save Config".
|
||||
_officialRow(base, enabled) {
|
||||
const host = base ? base.replace(/^https?:\/\//, '').replace(/\/$/, '') : 'official catalog';
|
||||
const url = base || '';
|
||||
const off = enabled === false;
|
||||
return `
|
||||
<div class="domain-building-block" data-catalog-official style="${off ? 'opacity:.55;' : ''}">
|
||||
<div class="domain-header" style="align-items:center; gap:.6rem;">
|
||||
<div style="flex:1; display:flex; align-items:center; gap:.6rem; min-width:0;">
|
||||
<span style="display:inline-flex; align-items:center; padding:.15rem .55rem; border-radius:999px; background:rgba(46,204,113,.15); color:#2ecc71; font-weight:600; font-size:.8rem; white-space:nowrap;">✓ Official</span>
|
||||
<span style="opacity:.85; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
|
||||
${this._esc(host)}<span data-official-hint>${off ? ' <em style="opacity:.7;">(hidden from browse)</em>' : ''}</span>
|
||||
</span>
|
||||
<div class="domain-building-block" data-catalog-official style="${off ? 'opacity:.6;' : ''}">
|
||||
<div class="domain-header">
|
||||
<div class="catalog-official-field">
|
||||
<span class="catalog-official-badge">✓ Official</span>
|
||||
<input type="text" class="form-control catalog-input catalog-official-input"
|
||||
value="${this._esc(url)}" readonly tabindex="-1"
|
||||
title="Official catalog — always source #1${off ? ' (hidden from browse)' : ''}">
|
||||
</div>
|
||||
<input type="hidden" name="CFG_CATALOG_OFFICIAL_ENABLED" id="config-CFG_CATALOG_OFFICIAL_ENABLED" value="${off ? 'false' : 'true'}">
|
||||
<span data-official-action>${window.officialCatalogActionHTML(!off)}</span>
|
||||
@ -46,10 +47,14 @@ class CatalogManager {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
async _officialBase() {
|
||||
// Official catalog URL = the Release Host (the official catalog and the release
|
||||
// host are the same). Read from the loaded config; falls back to the generated
|
||||
// catalog data's source.base if for some reason it isn't present.
|
||||
_officialBase() {
|
||||
try {
|
||||
const r = await fetch('/data/apps/generated/registry_catalog.json', { cache: 'no-store' });
|
||||
if (r.ok) { const j = await r.json(); return (j.source && j.source.base) || ''; }
|
||||
const cfg = window.configData && window.configData.config;
|
||||
const v = cfg && cfg.CFG_RELEASE_BASE_URL && cfg.CFG_RELEASE_BASE_URL.value;
|
||||
if (v) return String(v).replace(/\/+$/, '');
|
||||
} catch (_) {}
|
||||
return '';
|
||||
}
|
||||
@ -64,7 +69,7 @@ class CatalogManager {
|
||||
|
||||
const officialItem = configItems.find(i => i.key === 'CFG_CATALOG_OFFICIAL_ENABLED') || {};
|
||||
const officialEnabled = String(officialItem.value == null ? 'true' : officialItem.value) !== 'false';
|
||||
const officialBase = await this._officialBase();
|
||||
const officialBase = this._officialBase();
|
||||
|
||||
let blocks = this._officialRow(officialBase, officialEnabled);
|
||||
withContent.forEach(key => {
|
||||
@ -82,13 +87,8 @@ class CatalogManager {
|
||||
</div>
|
||||
</div>
|
||||
<div class="domains-divider"></div>
|
||||
<div class="traefik-warning-banner">
|
||||
<div class="traefik-warning-content">
|
||||
<span class="traefik-warning-icon">🛈</span>
|
||||
<div class="traefik-warning-text">
|
||||
<strong>The official catalog is always included.</strong> Add third-party catalog URLs to browse more apps — third-party sources are <em>unverified</em>.
|
||||
</div>
|
||||
</div>
|
||||
<div class="catalog-note">
|
||||
<span class="catalog-note-icon">🛈</span><strong>The official catalog is always included.</strong> Add third-party catalog URLs to browse more apps — third-party sources are <em>unverified</em>.
|
||||
</div>
|
||||
<div class="domain-building-blocks">
|
||||
${blocks}
|
||||
@ -212,11 +212,11 @@ window._setOfficialCatalog = function (enabled) {
|
||||
if (input) input.value = enabled ? 'true' : 'false';
|
||||
const row = document.querySelector('[data-catalog-official]');
|
||||
if (row) {
|
||||
row.style.opacity = enabled ? '' : '.55';
|
||||
row.style.opacity = enabled ? '' : '.6';
|
||||
const action = row.querySelector('[data-official-action]');
|
||||
if (action) action.innerHTML = window.officialCatalogActionHTML(enabled);
|
||||
const hint = row.querySelector('[data-official-hint]');
|
||||
if (hint) hint.innerHTML = enabled ? '' : ' <em style="opacity:.7;">(hidden from browse)</em>';
|
||||
const urlInput = row.querySelector('.catalog-official-input');
|
||||
if (urlInput) urlInput.title = 'Official catalog — always source #1' + (enabled ? '' : ' (hidden from browse)');
|
||||
}
|
||||
if (window.notificationSystem) {
|
||||
window.notificationSystem.info(enabled
|
||||
|
||||
@ -279,6 +279,48 @@
|
||||
padding: 16px 18px;
|
||||
}
|
||||
|
||||
/* Catalog info note — icon inline with the text, matches the content-box look. */
|
||||
.catalog-note {
|
||||
background: rgba(0, 0, 0, 0.20);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 10px;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 16px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.catalog-note strong { color: var(--text-primary); font-weight: 600; margin-right: 2px; }
|
||||
.catalog-note em { font-style: normal; color: var(--status-warning); font-weight: 600; }
|
||||
.catalog-note-icon { margin-right: 6px; }
|
||||
|
||||
/* Official catalog row — read-only URL input with a pinned badge overlaid; same
|
||||
height/box as the third-party rows. */
|
||||
.catalog-official-field { position: relative; flex: 1; min-width: 0; }
|
||||
.catalog-official-field .catalog-official-input {
|
||||
width: 100%;
|
||||
padding-left: 84px;
|
||||
opacity: 0.9;
|
||||
cursor: default;
|
||||
}
|
||||
.catalog-official-badge {
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
background: rgba(46, 204, 113, 0.15);
|
||||
color: #2ecc71;
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Responsive column counts — colocated here (and not in style.css)
|
||||
because the base 3-column rule above loads later than style.css,
|
||||
so the unscoped base would otherwise win the cascade against the
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user