admin: tables fit a phone, their first cell carrying the hidden columns, and no positioned label widens the page
This commit is contained in:
@@ -5,6 +5,7 @@ import InlineError from "@/lib/InlineError";
|
||||
import { upstreamCreateMutation, upstreamDeleteMutation, upstreamUpdateMutation, upstreamsQuery } from "@/lib/queries";
|
||||
import type { Upstream, UpstreamInput } from "@/lib/types";
|
||||
import ConfirmDialog from "@/ui/ConfirmDialog";
|
||||
import FactLine from "@/ui/FactLine";
|
||||
import { styles as shared } from "@/ui/styles";
|
||||
import { colors } from "@/ui/tokens.stylex";
|
||||
import Switch from "@/ui/Switch";
|
||||
@@ -16,18 +17,41 @@ import { styles as config } from "./styles";
|
||||
|
||||
const INTRO = "The pool is rebuilt as you save, so an edit here applies to the next query.";
|
||||
|
||||
/**
|
||||
* Narrower than the four columns side by side: below it the table keeps URL,
|
||||
* Enabled and the actions, and the URL cell carries the rest.
|
||||
*/
|
||||
const COMPACT = "@container (max-width: 42rem)";
|
||||
|
||||
const styles = stylex.create({
|
||||
/** Cut to one line beside the other columns; whole, wrapping, where it is the row's only text column. */
|
||||
url: {
|
||||
display: "block",
|
||||
maxWidth: "18rem",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
whiteSpace: { default: "nowrap", [COMPACT]: "normal" },
|
||||
overflowWrap: "anywhere",
|
||||
fontWeight: 500,
|
||||
},
|
||||
unbroken: {
|
||||
overflowWrap: "anywhere",
|
||||
},
|
||||
wide: {
|
||||
display: { default: null, [COMPACT]: "none" },
|
||||
},
|
||||
compact: {
|
||||
display: { default: "none", [COMPACT]: "block" },
|
||||
marginTop: "0.125rem",
|
||||
color: colors.textMuted,
|
||||
overflowWrap: "anywhere",
|
||||
},
|
||||
/** Stacked in the narrow form, which gives the first cell the width; the row is several lines tall there already. */
|
||||
actions: {
|
||||
display: "flex",
|
||||
gap: "0.75rem",
|
||||
flexDirection: { default: null, [COMPACT]: "column" },
|
||||
alignItems: { default: null, [COMPACT]: "flex-start" },
|
||||
gap: { default: "0.75rem", [COMPACT]: "0.5rem" },
|
||||
},
|
||||
dimWhenDisabled: {
|
||||
opacity: { default: 1, ":disabled": 0.5 },
|
||||
@@ -37,6 +61,17 @@ const styles = stylex.create({
|
||||
},
|
||||
});
|
||||
|
||||
/** The hidden columns' facts for the compact URL cell; an empty TLS name has nothing to say there. */
|
||||
function UpstreamFacts({ upstream }: { upstream: Upstream }) {
|
||||
const facts = [`Priority ${upstream.priority}`];
|
||||
if (upstream.tls_name !== "") facts.push(`TLS name ${upstream.tls_name}`);
|
||||
return (
|
||||
<span {...stylex.props(styles.compact, shared.tabularNums)}>
|
||||
<FactLine facts={facts} />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export default function UpstreamsTab() {
|
||||
const upstreams = useQuery(upstreamsQuery());
|
||||
return (
|
||||
@@ -78,18 +113,21 @@ function UpstreamsReadOnly({ upstreams }: { upstreams: Upstream[] }) {
|
||||
<thead>
|
||||
<tr>
|
||||
<th {...stylex.props(shared.th)}>URL</th>
|
||||
<th {...stylex.props(shared.th)}>Priority</th>
|
||||
<th {...stylex.props(shared.th, styles.wide)}>Priority</th>
|
||||
<th {...stylex.props(shared.th)}>Enabled</th>
|
||||
<th {...stylex.props(shared.th)}>TLS name</th>
|
||||
<th {...stylex.props(shared.th, styles.wide)}>TLS name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{upstreams.map((u) => (
|
||||
<tr key={u.id}>
|
||||
<td {...stylex.props(shared.td, shared.mono)}>{u.url}</td>
|
||||
<td {...stylex.props(shared.td, shared.tabularNums)}>{u.priority}</td>
|
||||
<td {...stylex.props(shared.td, styles.unbroken)}>
|
||||
<span {...stylex.props(shared.mono)}>{u.url}</span>
|
||||
<UpstreamFacts upstream={u} />
|
||||
</td>
|
||||
<td {...stylex.props(shared.td, shared.tabularNums, styles.wide)}>{u.priority}</td>
|
||||
<td {...stylex.props(shared.td)}>{String(u.enabled)}</td>
|
||||
<td {...stylex.props(shared.td)}>
|
||||
<td {...stylex.props(shared.td, styles.unbroken, styles.wide)}>
|
||||
{u.tls_name === "" ? (
|
||||
<span {...stylex.props(styles.absent)}>empty</span>
|
||||
) : (
|
||||
@@ -151,9 +189,9 @@ function UpstreamsEditor({ upstreams }: { upstreams: Upstream[] }) {
|
||||
<thead>
|
||||
<tr>
|
||||
<th {...stylex.props(shared.th)}>URL</th>
|
||||
<th {...stylex.props(shared.th)}>Priority</th>
|
||||
<th {...stylex.props(shared.th, styles.wide)}>Priority</th>
|
||||
<th {...stylex.props(shared.th)}>Enabled</th>
|
||||
<th {...stylex.props(shared.th)}>TLS name</th>
|
||||
<th {...stylex.props(shared.th, styles.wide)}>TLS name</th>
|
||||
<th {...stylex.props(shared.th)}>
|
||||
<span {...stylex.props(shared.srOnly)}>Actions</span>
|
||||
</th>
|
||||
@@ -166,8 +204,9 @@ function UpstreamsEditor({ upstreams }: { upstreams: Upstream[] }) {
|
||||
<span {...stylex.props(styles.url)} title={u.url}>
|
||||
{u.url}
|
||||
</span>
|
||||
<UpstreamFacts upstream={u} />
|
||||
</td>
|
||||
<td {...stylex.props(shared.td, shared.tabularNums)}>{u.priority}</td>
|
||||
<td {...stylex.props(shared.td, shared.tabularNums, styles.wide)}>{u.priority}</td>
|
||||
<td {...stylex.props(shared.td)}>
|
||||
<Switch
|
||||
aria-label={`${u.url} enabled`}
|
||||
@@ -176,7 +215,9 @@ function UpstreamsEditor({ upstreams }: { upstreams: Upstream[] }) {
|
||||
onChange={() => toggleEnabled(u)}
|
||||
/>
|
||||
</td>
|
||||
<td {...stylex.props(shared.td)}>{u.tls_name === "" ? "—" : u.tls_name}</td>
|
||||
<td {...stylex.props(shared.td, styles.unbroken, styles.wide)}>
|
||||
{u.tls_name === "" ? "—" : u.tls_name}
|
||||
</td>
|
||||
<td {...stylex.props(shared.td)}>
|
||||
<div {...stylex.props(styles.actions)}>
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user