portal: multi-line topic scope input + 'Add topic' on existing MQTT clients
Matches settings' new multi-topic-per-client support: the create form's Topic scope field is now a textarea (one pattern per line), the list shows all of a client's scopes, and a '+ Topic' button lets an admin grant an existing client more topic access without recreating it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
411911c4c8
commit
06690f0581
1 changed files with 29 additions and 4 deletions
|
|
@ -997,6 +997,19 @@ function MqttClientsTab() {
|
|||
if (res.ok) load()
|
||||
}
|
||||
|
||||
async function addTopic(c: MqttClient) {
|
||||
const topic = prompt(`Add a topic scope to "${c.name}" (e.g. hvac/mhi/#) — existing scopes are kept:`)
|
||||
if (!topic || !topic.trim()) return
|
||||
const res = await fetch(`/settings/api/mqtt-clients/${c.id}`, {
|
||||
method: 'PATCH', credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ add_topic_scope: topic.trim() }),
|
||||
})
|
||||
const data = await res.json()
|
||||
if (!res.ok) { alert(data.error || 'Failed to add topic'); return }
|
||||
load()
|
||||
}
|
||||
|
||||
function copyPassword() {
|
||||
if (!created) return
|
||||
navigator.clipboard.writeText(created.password)
|
||||
|
|
@ -1040,9 +1053,12 @@ function MqttClientsTab() {
|
|||
placeholder="e.g. Kitchen Flash Reader" style={inputStyle} />
|
||||
</label>
|
||||
<label style={{ display: 'flex', flexDirection: 'column', gap: '0.3rem' }}>
|
||||
<span style={{ fontSize: '0.78rem', fontWeight: 600, color: 'var(--text-mid)' }}>Topic scope</span>
|
||||
<input value={topicScope} onChange={e => setTopicScope(e.target.value)}
|
||||
placeholder="e.g. utilities/kitchen-meter/# or shellies/#" style={{ ...inputStyle, fontFamily: 'monospace' }} />
|
||||
<span style={{ fontSize: '0.78rem', fontWeight: 600, color: 'var(--text-mid)' }}>
|
||||
Topic scope
|
||||
<span style={{ fontWeight: 400, color: 'var(--text-mid)' }}> — one per line if it needs more than one</span>
|
||||
</span>
|
||||
<textarea value={topicScope} onChange={e => setTopicScope(e.target.value)} rows={2}
|
||||
placeholder={'e.g. shellies/#\nhvac/mhi/#'} style={{ ...inputStyle, fontFamily: 'monospace', resize: 'vertical' }} />
|
||||
</label>
|
||||
<div style={{ display: 'flex', gap: '1.5rem' }}>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: '0.4rem', fontSize: '0.85rem', color: 'var(--text-dark)' }}>
|
||||
|
|
@ -1143,13 +1159,22 @@ function MqttClientsTab() {
|
|||
)}
|
||||
</div>
|
||||
<div style={{ fontSize: '0.72rem', color: 'var(--text-mid)', fontFamily: 'monospace' }}>
|
||||
{c.topic_scope}
|
||||
{c.topic_scope.split('\n').join(', ')}
|
||||
<span style={{ marginLeft: '0.6rem', fontFamily: 'sans-serif' }}>
|
||||
{[c.can_publish && 'publish', c.can_subscribe && 'subscribe'].filter(Boolean).join(' + ')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ flexShrink: 0, display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
|
||||
{c.active && (
|
||||
<button onClick={() => addTopic(c)} title="Add another topic scope to this client" style={{
|
||||
background: 'transparent', color: 'var(--text-mid)',
|
||||
border: '1px solid var(--card-border)', borderRadius: '6px',
|
||||
padding: '0.35rem 0.85rem', fontSize: '0.78rem', fontWeight: 600, cursor: 'pointer',
|
||||
}}>
|
||||
+ Topic
|
||||
</button>
|
||||
)}
|
||||
{c.active ? (
|
||||
<button onClick={() => revoke(c)} style={{
|
||||
background: 'transparent', color: 'var(--text-mid)',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue