Files
Warp/apps/admin/src/views/NoticesView.vue
T
tajniak81andClaude Opus 5.5 7e5e38c921 Admin panel (warp-admin) and the apps/ui design system
apps/ui: Warp's design system for Vue 3 + Tailwind v4. Tokens, fonts,
icons and logo come from the brand package, with a Tailwind theme on the
tokens and Vue components on the brand component styles.

apps/admin: the admin panel as a separate, optional service. warp-admin
embeds the built Vue app and proxies only the login endpoints and
/_warp/admin/v1 to the homeserver. Pages: dashboard, users, rooms,
federation, registration and tokens, server notices, application
services, audit log.

Also: pnpm workspace, go.work entry, Dockerfile, an `admin` compose
profile, Makefile targets, a CI job with a proxy smoke test, and docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:05:16 +02:00

73 lines
2.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, ref } from 'vue'
import { WBanner, WButton, WTextArea, WTextField } from '@warp/ui'
import { sendNotice } from '@/api/admin'
import Mxid from '@/components/Mxid.vue'
import PageHeader from '@/components/PageHeader.vue'
import { useAction } from '@/lib/useLoad'
import { useSession } from '@/stores/session'
const session = useSession()
const user = ref('')
const body = ref('')
const send = useAction()
const last = ref<{ user: string; room: string } | null>(null)
const target = computed(() => {
const v = user.value.trim()
if (!v) return ''
return v.startsWith('@') ? v : `@${v}:${session.serverName}`
})
async function submit() {
let room = ''
const to = target.value
const ok = await send.run(async () => {
room = (await sendNotice(to, body.value.trim())).room_id
})
if (ok) {
last.value = { user: to, room }
body.value = ''
}
}
</script>
<template>
<PageHeader
title="Server notices"
description="Messages from the server to one of its users, in a room they can read but not reply in."
/>
<WBanner v-if="send.error.value" tone="danger" class="mb-4">
{{ send.error.value }}
</WBanner>
<WBanner v-else-if="last" tone="success" title="Notice sent" class="mb-4">
<Mxid :value="last.user" /> will see it in their server notices room <Mxid :value="last.room" />.
</WBanner>
<form class="wp-card flex max-w-2xl flex-col gap-4 p-4" @submit.prevent="submit">
<WTextField
v-model="user"
wide
mono
label="User"
:hint="target && !user.trim().startsWith('@') ? target : 'A localpart or a full Matrix ID on this server'"
:placeholder="`@alice:${session.serverName}`"
autocomplete="off"
spellcheck="false"
required
/>
<WTextArea v-model="body" label="Message" placeholder="Maintenance at 22:00 UTC." required rows="5" />
<p class="small text-ink-muted">
The user doesn’t have to be online: the invite and the message wait for them. Needs
<code class="code">server_notices.enabled</code> and a signing key.
</p>
<div>
<WButton type="submit" variant="primary" icon="send" :loading="send.busy.value" :disabled="!target || !body.trim()">
Send notice
</WButton>
</div>
</form>
</template>