Fix homepage external link placement and publish sanitization
This commit is contained in:
+115
-3
@@ -1613,6 +1613,8 @@ export default function AdminPage({ content, onSave, onLogout }: Props) {
|
||||
function getCustomLinkPlacementLabel(placement: CustomLink['placement']) {
|
||||
if (placement === 'platforms') return 'Homepage listen/platform links'
|
||||
if (placement === 'footer') return 'Footer navigation links'
|
||||
if (placement === 'otherSites') return 'Other site links in footer dropdown'
|
||||
if (placement === 'externalSites') return 'Homepage external site links'
|
||||
return 'Downloads page (More Resources)'
|
||||
}
|
||||
|
||||
@@ -1755,6 +1757,26 @@ export default function AdminPage({ content, onSave, onLogout }: Props) {
|
||||
}))
|
||||
}
|
||||
|
||||
function addOtherSiteLink() {
|
||||
setForm(f => ({
|
||||
...f,
|
||||
customLinks: [
|
||||
...(f.customLinks ?? []),
|
||||
{ id: Date.now().toString(36), label: '', url: '', imageUrl: '', placement: 'otherSites' as const },
|
||||
],
|
||||
}))
|
||||
}
|
||||
|
||||
function addExternalSiteLink() {
|
||||
setForm(f => ({
|
||||
...f,
|
||||
customLinks: [
|
||||
...(f.customLinks ?? []),
|
||||
{ id: Date.now().toString(36), label: '', url: '', imageUrl: '', description: '', placement: 'externalSites' as const },
|
||||
],
|
||||
}))
|
||||
}
|
||||
|
||||
function addResource() {
|
||||
setForm(f => ({
|
||||
...f,
|
||||
@@ -3781,14 +3803,61 @@ export default function AdminPage({ content, onSave, onLogout }: Props) {
|
||||
<p>Add links to show in platform buttons, footer navigation, or the More Resources download library.</p>
|
||||
</div>
|
||||
|
||||
<div className="admin-panel-subhead">
|
||||
<h3>Homepage External Links</h3>
|
||||
<p>Links shown on the homepage, separate from the footer.</p>
|
||||
</div>
|
||||
{(form.customLinks ?? []).filter(link => link.placement === 'externalSites').length === 0 && (
|
||||
<p className="admin-stats-note">No homepage external links yet.</p>
|
||||
)}
|
||||
{(form.customLinks ?? []).filter(link => link.placement === 'externalSites').map(link => (
|
||||
<div key={link.id} className="admin-array-row">
|
||||
<div className="admin-array-fields">
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`external-site-link-label-${link.id}`}>Label</label>
|
||||
<input id={`external-site-link-label-${link.id}`} type="text" value={link.label} placeholder="e.g. Bible study partner" onChange={e => updateLink(link.id, 'label', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`external-site-link-url-${link.id}`}>URL</label>
|
||||
<input id={`external-site-link-url-${link.id}`} type="url" value={link.url} placeholder="https://..." onChange={e => updateLink(link.id, 'url', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`external-site-link-description-${link.id}`}>Description</label>
|
||||
<textarea id={`external-site-link-description-${link.id}`} rows={3} value={link.description ?? ''} placeholder="Short description shown on the homepage" onChange={e => updateLink(link.id, 'description', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`external-site-link-image-${link.id}`}>Image URL</label>
|
||||
<input id={`external-site-link-image-${link.id}`} type="text" value={link.imageUrl ?? ''} placeholder="/uploads/example.png" onChange={e => updateLink(link.id, 'imageUrl', e.target.value)} />
|
||||
{renderImageAssetSelector(link.imageUrl, value => updateLink(link.id, 'imageUrl', value), `external-site-link-image-${link.id}-asset`)}
|
||||
{renderImagePreview(link.imageUrl, `${link.label || 'External site link'} image preview`)}
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`external-site-link-tags-${link.id}`}>Tags</label>
|
||||
<input id={`external-site-link-tags-${link.id}`} type="text" value={(link.tags ?? []).join(', ')} placeholder="external, homepage, ministry" onChange={e => updateLink(link.id, 'tags', e.target.value.split(',').map(tag => tag.trim()).filter(Boolean))} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label>Quick Action</label>
|
||||
<button type="button" className="btn-admin-apply" onClick={() => updateLink(link.id, 'placement', 'footer')}>Move to Footer Nav</button>
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label>Shows On</label>
|
||||
<p className="admin-stats-note">{getCustomLinkPlacementLabel(link.placement)}</p>
|
||||
<a href={getCustomLinkPreviewPath(link.placement)} target="_blank" rel="noopener noreferrer" className="btn-admin-secondary">Preview Destination Page</a>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" className="btn-admin-remove" onClick={() => removeLink(link.id)}>Remove</button>
|
||||
</div>
|
||||
))}
|
||||
<button type="button" className="btn-admin-add" onClick={addExternalSiteLink}>+ Add Homepage External Link</button>
|
||||
|
||||
<div className="admin-panel-subhead">
|
||||
<h3>Platform + Footer Links</h3>
|
||||
<p>Links that appear on the listen buttons row or footer nav.</p>
|
||||
</div>
|
||||
{(form.customLinks ?? []).filter(link => link.placement !== 'resources').length === 0 && (
|
||||
{(form.customLinks ?? []).filter(link => link.placement !== 'resources' && link.placement !== 'otherSites' && link.placement !== 'externalSites').length === 0 && (
|
||||
<p className="admin-stats-note">No custom links yet.</p>
|
||||
)}
|
||||
{(form.customLinks ?? []).filter(link => link.placement !== 'resources').map(link => (
|
||||
{(form.customLinks ?? []).filter(link => link.placement !== 'resources' && link.placement !== 'otherSites' && link.placement !== 'externalSites').map(link => (
|
||||
<div key={link.id} className="admin-array-row">
|
||||
<div className="admin-array-fields">
|
||||
<div className="admin-field">
|
||||
@@ -3830,7 +3899,50 @@ export default function AdminPage({ content, onSave, onLogout }: Props) {
|
||||
<button type="button" className="btn-admin-remove" onClick={() => removeLink(link.id)}>Remove</button>
|
||||
</div>
|
||||
))}
|
||||
<button type="button" className="btn-admin-add" onClick={addLink}>+ Add Link</button>
|
||||
<button type="button" className="btn-admin-add" onClick={addLink}>+ Add Platform/Footer Link</button>
|
||||
|
||||
<div className="admin-panel-subhead">
|
||||
<h3>Other Site Links</h3>
|
||||
<p>External links you want to surface in the footer dropdown.</p>
|
||||
</div>
|
||||
{(form.customLinks ?? []).filter(link => link.placement === 'otherSites').length === 0 && (
|
||||
<p className="admin-stats-note">No other site links yet.</p>
|
||||
)}
|
||||
{(form.customLinks ?? []).filter(link => link.placement === 'otherSites').map(link => (
|
||||
<div key={link.id} className="admin-array-row">
|
||||
<div className="admin-array-fields">
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`other-site-link-label-${link.id}`}>Label</label>
|
||||
<input id={`other-site-link-label-${link.id}`} type="text" value={link.label} placeholder="e.g. Recommended ministry" onChange={e => updateLink(link.id, 'label', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`other-site-link-url-${link.id}`}>URL</label>
|
||||
<input id={`other-site-link-url-${link.id}`} type="url" value={link.url} placeholder="https://..." onChange={e => updateLink(link.id, 'url', e.target.value)} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`other-site-link-image-${link.id}`}>Image URL</label>
|
||||
<input id={`other-site-link-image-${link.id}`} type="text" value={link.imageUrl ?? ''} placeholder="/uploads/example.png" onChange={e => updateLink(link.id, 'imageUrl', e.target.value)} />
|
||||
{renderImageAssetSelector(link.imageUrl, value => updateLink(link.id, 'imageUrl', value), `other-site-link-image-${link.id}-asset`)}
|
||||
{renderImagePreview(link.imageUrl, `${link.label || 'Other site link'} image preview`)}
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label htmlFor={`other-site-link-tags-${link.id}`}>Tags</label>
|
||||
<input id={`other-site-link-tags-${link.id}`} type="text" value={(link.tags ?? []).join(', ')} placeholder="external, ministry, study" onChange={e => updateLink(link.id, 'tags', e.target.value.split(',').map(tag => tag.trim()).filter(Boolean))} />
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label>Quick Action</label>
|
||||
<button type="button" className="btn-admin-apply" onClick={() => updateLink(link.id, 'placement', 'footer')}>Move to Footer Nav</button>
|
||||
</div>
|
||||
<div className="admin-field">
|
||||
<label>Shows On</label>
|
||||
<p className="admin-stats-note">{getCustomLinkPlacementLabel(link.placement)}</p>
|
||||
<a href={getCustomLinkPreviewPath(link.placement)} target="_blank" rel="noopener noreferrer" className="btn-admin-secondary">Preview Destination Page</a>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" className="btn-admin-remove" onClick={() => removeLink(link.id)}>Remove</button>
|
||||
</div>
|
||||
))}
|
||||
<button type="button" className="btn-admin-add" onClick={addOtherSiteLink}>+ Add Other Site Link</button>
|
||||
|
||||
<div className="admin-panel-subhead">
|
||||
<h3>More Resources Links</h3>
|
||||
|
||||
Reference in New Issue
Block a user