⋯ 1,224 lines Show the 1,224 lines above this hunk @@ -1225,7 +1225,7 @@ onMount(() => { 1225 1225 @ if ( user & & projectsUnavailable ) 1226 1226 < div class = "py-24 text-center" > 1227 1227 < p class = "text-muted text-sm" > < span class = "font-semibold text-ink" > Can 't reach your settings right now.</span> Make sure Postgres is provisioned.</p> 1228 - < p class = "mt-2 text-subtle text-xs" > Nothing has been changed — reload once the database is back . < / p > 1228 + < p class = "mt-2 text-subtle text-xs" > Nothing has been changed . Reload once the database is back . < / p > 1229 1229 < / div > 1230 1230 @ endif 1231 1231 ⋯ 69 lines Show the 69 lines above this hunk @@ -1301,7 +1301,7 @@ onMount(() => { 1301 1301 < div class = "px-5 py-5 app-panel" > 1302 1302 < p class = "mb-4 text-sm text-subtle" > 1303 1303 This key authorizes log ingest for < span class = "font-mono text-muted" > { { activeProject ? . name } } < / span > . 1304 - It 's a public identifier (safe to ship in client code), not a secret — it says <em>which</em> project an entry belongs to, and grants no read access. 1304 + It 's a public identifier (safe to ship in client code), not a secret : it says <em>which</em> project an entry belongs to, and grants no read access. 1305 1305 < / p > 1306 1306 < div class = "flex flex-wrap gap-2 items-center" > 1307 1307 < code class = "flex-1 px-3.5 py-2.5 min-w-[220px] font-mono text-ink text-sm tracking-[0.01em] truncate bg-canvas border border-line rounded-[10px] focus:border-[color-mix(in_srgb,var(--accent)_55%,var(--border))] focus:outline-none" : text = "keyShown()" > { { keyMask } } < / code > ⋯ 2 lines Show the 2 lines above this hunk @@ -1310,7 +1310,7 @@ onMount(() => { 1310 1310 < Button variant = "ghost" @ click = "rotateKey" : loading = "rotating()" className = "btn-danger btn-sm" > Rotate < / Button > 1311 1311 < / div > 1312 1312 < p class = "mt-3.5 leading-relaxed text-subtle text-xs" > 1313 - Rotating generates a new key and < span class = "text-warn" > invalidates the current one immediately < / span > — anything still sending the old key will get 401 until you update it ( < span class = "font-mono" > X - LogHQ - Key < / span > ) . 1313 + Rotating generates a new key and < span class = "text-warn" > invalidates the current one immediately < / span > . Anything still sending the old key will get 401 until you update it ( < span class = "font-mono" > X - LogHQ - Key < / span > ) . 1314 1314 < / p > 1315 1315 < span class = "mt-2 text-ok text-xs" : show = "!!keyNote()" : class = "keyNoteOk() ? 'mt-2 text-xs text-ok' : 'mt-2 text-xs text-accent'" > { { keyNote ( ) } } < / span > 1316 1316 < / div > ⋯ 99 lines Show the 99 lines above this hunk @@ -1416,9 +1416,9 @@ onMount(() => { 1416 1416 < span class = "grid place-items-center shrink-0 h-8 w-8 font-semibold text-subtle bg-[color-mix(in_srgb,var(--text-3)_12%,var(--panel))] rounded-lg" > { { ( i . email | | '?' ) . charAt ( 0 ) . toUpperCase ( ) } } < / span > 1417 1417 < div class = "flex-1 min-w-0" > 1418 1418 < div class = "font-medium text-sm truncate" > { { i . email } } < / div > 1419 - < div class = "mt-0.5 text-subtle text-xs" > { { i . registered ? 'Has an account — pending accept' : 'Invite sent — awaiting sign-up' } } < / div > 1419 + < div class = "mt-0.5 text-subtle text-xs" > { { i . registered ? 'Has an account , pending accept' : 'Invite sent , awaiting sign-up' } } < / div > 1420 1420 < / div > 1421 - < span class = "px-[9px] py-0.5 font-semibold text-[11px] text-muted tracking-[0.02em] bg-[color-mix(in_srgb,var(--text-3)_18%,var(--panel))] rounded-[999px]" x - tooltip = "Pending — becomes a member once they accept" > Invited < / span > 1421 + < span class = "px-[9px] py-0.5 font-semibold text-[11px] text-muted tracking-[0.02em] bg-[color-mix(in_srgb,var(--text-3)_18%,var(--panel))] rounded-[999px]" x - tooltip = "Pending : becomes a member once they accept" > Invited < / span > 1422 1422 < button @ click = "copyJoin('', '')" : text = "joinBtnLabel('')" class = "btn-quiet btn-xs" x - tooltip = "Copy join link" > Copy link < / button > 1423 1423 < button @ click = "removeMember('')" : disabled = "removingMember() === ''" : text = "memberBtnLabel('')" class = "btn-danger btn-xs" x - tooltip = "Revoke invite" > Remove < / button > 1424 1424 < / div > ⋯ 16 lines Show the 16 lines above this hunk @@ -1441,7 +1441,7 @@ onMount(() => { 1441 1441 < section id = "alerts" class = "mb-10 scroll-mt-[84px]" > 1442 1442 < div class = "mb-3 font-semibold text-[13px] text-subtle tracking-[0.04em] uppercase" > Alerts < / div > 1443 1443 < p class = "mb-4 text-sm text-subtle" > 1444 - Add a Slack or Discord webhook and send a test to verify it . Automatic delivery isn 't live yet — 1444 + Add a Slack or Discord webhook and send a test to verify it . Automatic delivery isn 't live yet : 1445 1445 channels you add here are saved and testable , but loghq won 't fire on its own until log-based alert rules ship. 1446 1446 < / p > 1447 1447 < div class = "flex flex-col gap-2.5 mb-4" > ⋯ 41 lines Show the 41 lines above this hunk @@ -1489,7 +1489,7 @@ onMount(() => { 1489 1489 < button type = "button" @ click = "chType.set('discord')" data - sel = "0" : data - sel = "chType() === 'discord' ? '1' : '0'" class = "px-3 py-2.5 font-medium text-muted text-sm bg-panel border border-line rounded-[10px] [transition:all_0.12s_ease] seg seg-discord" > Discord < / button > 1490 1490 < / div > 1491 1491 < input : model = "whUrl" : placeholder = "whPlaceholder()" type = "url" aria - label = "Webhook URL" class = "mb-2 px-3.5 py-2.5 w-full font-mono text-ink text-sm bg-canvas border border-line rounded-[10px] focus:border-[color-mix(in_srgb,var(--accent)_55%,var(--border))] focus:outline-none" placeholder = "https://hooks.slack.com/services/…" autocomplete = "off" spellcheck = "false" > 1492 - < input : model = "whLabel" type = "text" aria - label = "Channel label" class = "mb-3 px-3.5 py-2.5 w-full text-ink text-sm bg-canvas border border-line rounded-[10px] focus:border-[color-mix(in_srgb,var(--accent)_55%,var(--border))] focus:outline-none" placeholder = "Label (optional) — e.g. #alerts" maxlength = "255" > 1492 + < input : model = "whLabel" type = "text" aria - label = "Channel label" class = "mb-3 px-3.5 py-2.5 w-full text-ink text-sm bg-canvas border border-line rounded-[10px] focus:border-[color-mix(in_srgb,var(--accent)_55%,var(--border))] focus:outline-none" placeholder = "Label (optional) , e.g. #alerts" maxlength = "255" > 1493 1493 < div class = "flex gap-3 items-center" > 1494 1494 < Button variant = "ghost" @ click = "addChannel" : loading = "adding()" className = "btn-cta btn-solid" > Add channel < / Button > 1495 1495 < span class = "text-ok text-xs" : show = "!!whNote()" : class = "whNoteOk() ? 'text-xs text-ok' : 'text-xs text-accent'" > { { whNote ( ) } } < / span > ⋯ 85 lines Show the 85 lines above this hunk @@ -1581,7 +1581,7 @@ onMount(() => { 1581 1581 < p class = "text-sm text-subtle" > < span class = "font-mono text-muted" > { { activeProject ? . name } } < / span > is archived and isn ’ t accepting new logs . Unarchiving resumes ingestion right away . < / p > 1582 1582 @ else 1583 1583 < div class = "mb-0.5 font-semibold text-sm" > Archive this project < / div > 1584 - < p class = "text-sm text-subtle" > Rejects new log entries for < span class = "font-mono text-muted" > { { activeProject ? . name } } < / span > with a 403. Everything already stored is kept — you can unarchive anytime . < / p > 1584 + < p class = "text-sm text-subtle" > Rejects new log entries for < span class = "font-mono text-muted" > { { activeProject ? . name } } < / span > with a 403. Everything already stored is kept , and you can unarchive anytime . < / p > 1585 1585 @ endif 1586 1586 < / div > 1587 1587 < Button variant = "ghost" @ click = "openArchive" : loading = "archiving()" className = "flex-none whitespace-nowrap btn-cta btn-danger" > { { activeProject ? . is_active = = = false ? 'Unarchive' : 'Archive' } } < / Button >