mirror of
https://github.com/block/buzz.git
synced 2026-10-30 14:01:37 +00:00
fix(desktop): disclose requested channel lifetime
Co-authored-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz> Signed-off-by: Wrench <0eabe6ea5758c1e4c5b68cea4ac42b32c479072883cb28da8110b4a47c32b9a1@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import React from "react";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
|
||||
import { ProjectChannelRequestDetails } from "./ProjectChannelRequestDialog.tsx";
|
||||
|
||||
function request(overrides = {}) {
|
||||
return {
|
||||
homeChannelId: "11111111-1111-4111-8111-111111111111",
|
||||
name: "release-planning",
|
||||
visibility: "private",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test("owner review shows an agent-requested temporary channel lifetime and cleanup consequence", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
React.createElement(ProjectChannelRequestDetails, {
|
||||
request: request({ ttlSeconds: 90_000 }),
|
||||
}),
|
||||
);
|
||||
|
||||
assert.match(html, />Lifetime</);
|
||||
assert.match(html, /Temporary · 1d1h/);
|
||||
assert.match(
|
||||
html,
|
||||
/Cleans up automatically after that period of inactivity\./,
|
||||
);
|
||||
});
|
||||
|
||||
test("owner review omits temporary-channel lifetime when none was requested", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
React.createElement(ProjectChannelRequestDetails, { request: request() }),
|
||||
);
|
||||
|
||||
assert.doesNotMatch(html, />Lifetime</);
|
||||
assert.doesNotMatch(html, /Temporary/);
|
||||
assert.doesNotMatch(html, /Cleans up automatically/);
|
||||
});
|
||||
@@ -8,8 +8,57 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/shared/ui/alert-dialog";
|
||||
import { formatTtlDuration } from "@/features/channels/lib/ephemeralChannel";
|
||||
import type { ProjectChannelRequest } from "@/features/projects/projectChannelRequest";
|
||||
import { useProjectChannelRequests } from "@/features/projects/useProjectChannelRequests";
|
||||
|
||||
type RequestedChannel = ProjectChannelRequest["request"];
|
||||
|
||||
/** Details an owner reviews before approving an agent-requested project channel. */
|
||||
export function ProjectChannelRequestDetails({
|
||||
request,
|
||||
}: {
|
||||
request: RequestedChannel;
|
||||
}) {
|
||||
return (
|
||||
<dl className="space-y-2 rounded-xl border border-border/60 bg-muted/25 p-3 text-sm">
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">Name</dt>
|
||||
<dd className="min-w-0 break-words text-foreground">#{request.name}</dd>
|
||||
</div>
|
||||
{request.description ? (
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">Description</dt>
|
||||
<dd className="min-w-0 break-words text-foreground">
|
||||
{request.description}
|
||||
</dd>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">Visibility</dt>
|
||||
<dd className="text-foreground">{request.visibility}</dd>
|
||||
</div>
|
||||
{request.ttlSeconds ? (
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">Lifetime</dt>
|
||||
<dd className="min-w-0 break-words text-foreground">
|
||||
Temporary · {formatTtlDuration(request.ttlSeconds)}. Cleans up
|
||||
automatically after that period of inactivity.
|
||||
</dd>
|
||||
</div>
|
||||
) : null}
|
||||
{request.templateName ? (
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">Template</dt>
|
||||
<dd className="min-w-0 break-words text-foreground">
|
||||
{request.templateName}
|
||||
</dd>
|
||||
</div>
|
||||
) : null}
|
||||
</dl>
|
||||
);
|
||||
}
|
||||
|
||||
/** Global owner-review surface for project-channel requests from managed agents. */
|
||||
export function ProjectChannelRequestDialog() {
|
||||
const management = useProjectChannelRequests();
|
||||
@@ -31,42 +80,7 @@ export function ProjectChannelRequestDialog() {
|
||||
before creating it.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
{request ? (
|
||||
<dl className="space-y-2 rounded-xl border border-border/60 bg-muted/25 p-3 text-sm">
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">Name</dt>
|
||||
<dd className="min-w-0 break-words text-foreground">
|
||||
#{request.name}
|
||||
</dd>
|
||||
</div>
|
||||
{request.description ? (
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">
|
||||
Description
|
||||
</dt>
|
||||
<dd className="min-w-0 break-words text-foreground">
|
||||
{request.description}
|
||||
</dd>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">
|
||||
Visibility
|
||||
</dt>
|
||||
<dd className="text-foreground">{request.visibility}</dd>
|
||||
</div>
|
||||
{request.templateName ? (
|
||||
<div className="flex gap-3">
|
||||
<dt className="w-24 shrink-0 text-muted-foreground">
|
||||
Template
|
||||
</dt>
|
||||
<dd className="min-w-0 break-words text-foreground">
|
||||
{request.templateName}
|
||||
</dd>
|
||||
</div>
|
||||
) : null}
|
||||
</dl>
|
||||
) : null}
|
||||
{request ? <ProjectChannelRequestDetails request={request} /> : null}
|
||||
{management.error ? (
|
||||
<p className="text-sm text-destructive">{management.error}</p>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user