contact messages: label is the enable switch; single-line settings row
Data.contact_enabled is gone: an empty contact label disables messaging (no buttons, no visitor icon, sends rejected). The settings row is one line — flag selector, label, email, subject as small boxes with tooltip instructions — and saves re-render the page in place so button/dialog strings update without a reload; the open dialog also re-reads its strings on page swaps. The built-in Contact us default survives only as the inert preview placeholder.
This commit is contained in:
1 parent
59fe426e5e
commit
8d577dc56e
8 files changed
+119
-114
No files matched your search
+52
-60
@@ -62,15 +62,14 @@ const brand = ref('')
|
||||
const theme = ref('')
|
||||
|
||||
// --- Messaging (contact) ---------------------------------------------------
|
||||
// Site-wide contact settings: the enabled toggle (combined with the
|
||||
// section header) and mailto address are global; the label (the
|
||||
// {contact:} buttons' default and the visitor dialog's title) and the
|
||||
// email subject are per-language strings — the LangSelect (the article
|
||||
// editor's flag dropdown, on the shared shell-wide editorLang) switches
|
||||
// the two text fields between the original and a translation override
|
||||
// (stored in the chunk-keyed trans store; auto translators fill the same
|
||||
// store, so this is the manual-override UI).
|
||||
const contactEnabled = ref(true)
|
||||
// One-line contact settings. The label (the {contact:} buttons' label and
|
||||
// the visitor dialog's title) doubles as the on/off switch: empty =
|
||||
// disabled. The label and email subject are per-language strings — the
|
||||
// LangSelect (the article editor's flag dropdown, on the shared shell-wide
|
||||
// editorLang) switches the two fields between the original and a
|
||||
// translation override (stored in the chunk-keyed trans store; auto
|
||||
// translators fill the same store, so this is the manual-override UI).
|
||||
// The email is global; its reveal after the PoW solve is server-side.
|
||||
const contactEmail = ref('')
|
||||
const contactLabel = ref('')
|
||||
const contactSubject = ref('')
|
||||
@@ -135,10 +134,18 @@ async function saveContact(tag = lang.value, label = '', subject = '') {
|
||||
}),
|
||||
})
|
||||
saveError.value = res.ok ? '' : '⚠️ changes could not be saved'
|
||||
if (res.ok) dropPageCache()
|
||||
if (res.ok) rerender()
|
||||
return
|
||||
}
|
||||
saveSettings()
|
||||
if (await saveSettings()) rerender()
|
||||
}
|
||||
|
||||
// The rendered {contact:} buttons are server HTML: after a save the page
|
||||
// re-renders (like a theme change), updating buttons and dialog strings
|
||||
// without a reload.
|
||||
async function rerender() {
|
||||
dropPageCache()
|
||||
loadPlain(path.value)
|
||||
}
|
||||
// Theme options come from the backend (theme folders on disk, see GET
|
||||
// /_api/settings), so added themes need no frontend changes.
|
||||
@@ -171,7 +178,6 @@ async function loadSettings() {
|
||||
]
|
||||
transition.value = s.transition || 'cube'
|
||||
transitionOptions.value = s.transitions || []
|
||||
contactEnabled.value = s.contact_enabled !== false
|
||||
contactEmail.value = s.contact_email || ''
|
||||
contactLabelOrig.value = s.contact_label || ''
|
||||
contactSubjectOrig.value = s.contact_subject || ''
|
||||
@@ -348,7 +354,6 @@ async function saveSettings(opts = {}) {
|
||||
custom_css: customCss.value,
|
||||
brand_html: brandHtml.value,
|
||||
transition: transition.value,
|
||||
contact_enabled: contactEnabled.value,
|
||||
contact_email: contactEmail.value,
|
||||
// The originals: while a translation override is being edited the
|
||||
// input refs hold the override, not the original.
|
||||
@@ -363,6 +368,7 @@ async function saveSettings(opts = {}) {
|
||||
} else {
|
||||
saveError.value = '⚠️ changes could not be saved'
|
||||
}
|
||||
return res.ok
|
||||
}
|
||||
|
||||
async function onThemeChange() {
|
||||
@@ -758,51 +764,34 @@ onUnmounted(() => {
|
||||
</section>
|
||||
|
||||
<section class="block">
|
||||
<div class="block-head">
|
||||
<div class="block-head msg-head">
|
||||
<LangSelect
|
||||
v-model="lang"
|
||||
:options="contactLangOptions"
|
||||
title="Language of the label/subject strings (auto translators fill these too; this edits the manual override)"
|
||||
/>
|
||||
<label
|
||||
class="msg-toggle"
|
||||
title="Visitor messaging ({contact:} buttons, corner icon)"
|
||||
>
|
||||
<input v-model="contactEnabled" type="checkbox" @change="saveSettings()" />
|
||||
<span class="field-label">messaging</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="field-grid">
|
||||
<label class="field">
|
||||
<span class="field-label">email</span>
|
||||
<input
|
||||
v-model="contactEmail"
|
||||
class="text-input"
|
||||
title="Contact email — a mailto link in the visitor dialog (empty = no link)"
|
||||
:disabled="!!translating"
|
||||
@input="debounce('contact-email', () => saveSettings())"
|
||||
/>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span class="field-label">label</span>
|
||||
<input
|
||||
v-model="contactLabel"
|
||||
class="text-input"
|
||||
title="Default {contact:} button label and visitor dialog title (empty = built-in default)"
|
||||
:placeholder="translating ? contactLabelOrig : 'Contact us'"
|
||||
@input="onContactInput"
|
||||
/>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span class="field-label">subject</span>
|
||||
<input
|
||||
v-model="contactSubject"
|
||||
class="text-input"
|
||||
title="Subject for the mailto link (empty = the label)"
|
||||
:placeholder="translating ? contactSubjectOrig : ''"
|
||||
@input="onContactInput"
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
v-model="contactLabel"
|
||||
class="text-input"
|
||||
:placeholder="translating ? contactLabelOrig : 'Contact us'"
|
||||
title="Messaging: the {contact:} button label and visitor dialog title — empty disables messaging"
|
||||
@input="onContactInput"
|
||||
/>
|
||||
<input
|
||||
v-model="contactEmail"
|
||||
class="text-input"
|
||||
placeholder="email"
|
||||
title="Contact email — a mailto link in the visitor dialog, revealed only after the proof of work is solved (empty = no link)"
|
||||
:disabled="!!translating"
|
||||
@input="debounce('contact-email', () => saveSettings())"
|
||||
/>
|
||||
<input
|
||||
v-model="contactSubject"
|
||||
class="text-input"
|
||||
:placeholder="translating ? contactSubjectOrig : 'subject'"
|
||||
title="Subject for the mailto link (empty = the label)"
|
||||
@input="onContactInput"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -936,13 +925,16 @@ onUnmounted(() => {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* The messaging block's single-line header: the article editor's flag
|
||||
selector, then the enabled toggle fused with the section label. */
|
||||
.msg-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
cursor: pointer;
|
||||
/* The messaging block: one line — the article editor's flag selector,
|
||||
then small text boxes (label = the enable switch, email, subject). */
|
||||
.msg-head {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.msg-head .text-input {
|
||||
flex: 1 1 7rem;
|
||||
min-width: 5rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.text-input {
|
||||
|
||||
@@ -54,6 +54,11 @@ function readContactStrings() {
|
||||
// PoW is solved and stays valid for the session.
|
||||
}
|
||||
|
||||
// Page swaps (fetch navigation, editor re-renders after settings saves)
|
||||
// carry fresh per-language config: keep the dialog strings in sync
|
||||
// without reopening.
|
||||
addEventListener('pagerite:page-fetched', readContactStrings)
|
||||
|
||||
// The panel is main content, not a sidebar: while open it holds paskia's
|
||||
// shared blur backdrop (refcounted, z-index 1099; the overlay itself sits
|
||||
// at 1100, below the auth iframe's 9999).
|
||||
|
||||
Reference in new issue
Block a user