@sentry/junior-dashboard 0.272.0 → 0.274.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +3 -3
- package/dist/client.js +69 -67
- package/dist/index.js +3 -3
- package/dist/tailwind.css +1 -1
- package/package.json +4 -4
- package/src/client/App.tsx +440 -430
- package/src/client/components/JuniorLogo.tsx +1 -1
- package/src/client/components/ProfileMenu.tsx +4 -41
- package/src/client/components/layout/DashboardChrome.tsx +9 -4
- package/src/client/components/layout/DashboardHeader.tsx +11 -51
- package/src/client/components/layout/NavRail.tsx +156 -0
- package/src/client/components/ui/sidebar.tsx +336 -0
- package/src/client/conversations/ConversationComposer.tsx +7 -4
- package/src/client/conversations/ConversationPage.tsx +3 -0
- package/src/client/conversations/ConversationSidebar.tsx +121 -60
- package/src/client/conversations/ConversationWorkspace.tsx +8 -3
- package/src/client/conversations/PendingMailboxStack.tsx +22 -9
- package/src/client/conversations/TranscriptMessageShell.tsx +19 -8
- package/src/client/conversations/TranscriptMessageView.tsx +8 -1
- package/src/client/conversations/TranscriptTurnContextView.tsx +1 -1
- package/src/client/conversations/composerAutocorrect.ts +12 -0
- package/src/client/conversations/conversationAge.ts +24 -0
- package/src/client/conversations/conversationOutbox.ts +19 -0
- package/src/client/conversations/conversationRoutes.ts +14 -5
- package/src/client/conversations/conversationSections.ts +64 -50
- package/src/client/conversations/eventTranscript.ts +6 -0
- package/src/client/conversations/queries.ts +1 -17
- package/src/client/conversations/transcript.ts +12 -2
- package/src/client/conversations/useConversationFinishedIndicators.ts +40 -8
- package/src/client/format.ts +8 -1
- package/src/client/pages/settings/SettingsPage.tsx +28 -0
- package/src/client/review-desk/ConversationReviewBar.tsx +20 -2
- package/src/client/review-desk/ReviewDeskPage.tsx +5 -1
- package/src/client/review-desk/queries.ts +34 -7
- package/src/client/types.ts +2 -0
- package/src/mock-reporting/routes.ts +1 -1
|
@@ -12,12 +12,14 @@ import {
|
|
|
12
12
|
import { Button } from "../../components/ui/button";
|
|
13
13
|
import { Input } from "../../components/ui/input";
|
|
14
14
|
import { Textarea } from "../../components/ui/textarea";
|
|
15
|
+
import { Checkbox } from "../../components/ui/checkbox";
|
|
15
16
|
import { Field, FieldDescription, FieldLabel } from "../../components/ui/field";
|
|
16
17
|
import { RadioGroup, RadioGroupItem } from "../../components/ui/radio-group";
|
|
17
18
|
import {
|
|
18
19
|
useConversationStartPosition,
|
|
19
20
|
type ConversationStartPosition,
|
|
20
21
|
} from "../../conversations/transcriptReadPosition";
|
|
22
|
+
import { useComposerAutocorrect } from "../../conversations/composerAutocorrect";
|
|
21
23
|
import { InlineError } from "../../components/InlineError";
|
|
22
24
|
import { Card } from "../../components/layout/Card";
|
|
23
25
|
import { DashboardApiError, fetchDashboardJson, patch, put } from "../../http";
|
|
@@ -105,6 +107,7 @@ export function SettingsPage({ identity }: SettingsPageProps) {
|
|
|
105
107
|
</Card>
|
|
106
108
|
</form>
|
|
107
109
|
<ConversationStartSetting />
|
|
110
|
+
<ComposerAutocorrectSetting />
|
|
108
111
|
<CustomizationForm />
|
|
109
112
|
</SettingsPageLayout>
|
|
110
113
|
);
|
|
@@ -166,6 +169,31 @@ function ConversationStartSetting() {
|
|
|
166
169
|
);
|
|
167
170
|
}
|
|
168
171
|
|
|
172
|
+
/** Let the user turn on keyboard autocorrect in the composer on this browser. */
|
|
173
|
+
function ComposerAutocorrectSetting() {
|
|
174
|
+
const [autocorrect, setAutocorrect] = useComposerAutocorrect();
|
|
175
|
+
return (
|
|
176
|
+
<Card className="mt-6 mb-0" padding="md" variant="raised">
|
|
177
|
+
<h2 className="m-0 text-lg font-bold">Message box</h2>
|
|
178
|
+
<label className="mt-4 flex cursor-pointer items-start gap-3">
|
|
179
|
+
<Checkbox
|
|
180
|
+
checked={autocorrect}
|
|
181
|
+
className="mt-0.5"
|
|
182
|
+
onCheckedChange={setAutocorrect}
|
|
183
|
+
/>
|
|
184
|
+
<span className="grid gap-0.5">
|
|
185
|
+
<span className="text-sm font-medium">Autocorrect</span>
|
|
186
|
+
<span className="text-xs text-dashboard-text-muted">
|
|
187
|
+
Let your keyboard correct spelling and capitalize sentences as you
|
|
188
|
+
type. This can change ids, paths, and code. This choice applies to
|
|
189
|
+
this browser.
|
|
190
|
+
</span>
|
|
191
|
+
</span>
|
|
192
|
+
</label>
|
|
193
|
+
</Card>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
169
197
|
/**
|
|
170
198
|
* Let the user save text that changes how the agent replies to them. The
|
|
171
199
|
* server returns 404 when the app does not enable this experiment.
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { ChevronRight } from "lucide-react";
|
|
2
|
-
import {
|
|
2
|
+
import { useSearchParams } from "react-router";
|
|
3
3
|
|
|
4
4
|
import { Drawer } from "../components/Drawer";
|
|
5
5
|
import { LoadMorePagination } from "../components/Pagination";
|
|
6
6
|
import { ReviewItemCard } from "./ReviewItemCard";
|
|
7
7
|
import { useReviewItemsData } from "./queries";
|
|
8
|
+
import {
|
|
9
|
+
CONVERSATION_REVIEW_OPEN,
|
|
10
|
+
CONVERSATION_REVIEW_PARAM,
|
|
11
|
+
} from "../conversations/conversationRoutes";
|
|
8
12
|
|
|
9
13
|
/** `more` marks a count of the loaded pages only, such as "50+". */
|
|
10
14
|
function itemCountLabel(count: number, more: boolean): string {
|
|
@@ -15,9 +19,23 @@ function itemCountLabel(count: number, more: boolean): string {
|
|
|
15
19
|
/**
|
|
16
20
|
* Show how many open Review items are linked to a Conversation, above its
|
|
17
21
|
* message box. The bar opens a side panel where the viewer can act on each.
|
|
22
|
+
* The URL owns the panel, so a sidebar link can open it.
|
|
18
23
|
*/
|
|
19
24
|
export function ConversationReviewBar(props: { conversationId: string }) {
|
|
20
|
-
const [
|
|
25
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
26
|
+
const open =
|
|
27
|
+
searchParams.get(CONVERSATION_REVIEW_PARAM) === CONVERSATION_REVIEW_OPEN;
|
|
28
|
+
const setOpen = (value: boolean) =>
|
|
29
|
+
setSearchParams(
|
|
30
|
+
(current) => {
|
|
31
|
+
const next = new URLSearchParams(current);
|
|
32
|
+
if (value)
|
|
33
|
+
next.set(CONVERSATION_REVIEW_PARAM, CONVERSATION_REVIEW_OPEN);
|
|
34
|
+
else next.delete(CONVERSATION_REVIEW_PARAM);
|
|
35
|
+
return next;
|
|
36
|
+
},
|
|
37
|
+
{ replace: true },
|
|
38
|
+
);
|
|
21
39
|
const { items, query } = useReviewItemsData({
|
|
22
40
|
conversationId: props.conversationId,
|
|
23
41
|
});
|
|
@@ -69,7 +69,11 @@ export function ReviewDeskPage() {
|
|
|
69
69
|
useDocumentTitle("Inbox");
|
|
70
70
|
const [searchParams] = useSearchParams();
|
|
71
71
|
const [search, setSearch, q] = useDebouncedSearchParam();
|
|
72
|
-
const {
|
|
72
|
+
const {
|
|
73
|
+
items: list,
|
|
74
|
+
moreArchived,
|
|
75
|
+
query: items,
|
|
76
|
+
} = useReviewItemsData({ forViewer: true, q });
|
|
73
77
|
const showBlocked = !q;
|
|
74
78
|
const blocked = useBlockedAutomationsData(showBlocked);
|
|
75
79
|
const blockedAutomations = showBlocked
|
|
@@ -26,16 +26,19 @@ const COUNT_REFRESH_MS = 60_000;
|
|
|
26
26
|
/**
|
|
27
27
|
* List the open Review items that the viewer can see, one page at a time.
|
|
28
28
|
* A search also finds archived items, with the first page. `items` holds the
|
|
29
|
-
* items of every loaded page, and `query` loads more.
|
|
29
|
+
* items of every loaded page, and `query` loads more. `forViewer` drops the
|
|
30
|
+
* items that are assigned only to other people.
|
|
30
31
|
*/
|
|
31
32
|
export function useReviewItemsData(filters: {
|
|
32
33
|
conversationId?: string;
|
|
34
|
+
forViewer?: boolean;
|
|
33
35
|
q?: string;
|
|
34
36
|
}) {
|
|
35
37
|
const params = new URLSearchParams();
|
|
36
38
|
if (filters.conversationId) {
|
|
37
39
|
params.set("conversationId", filters.conversationId);
|
|
38
40
|
}
|
|
41
|
+
if (filters.forViewer) params.set("for", "viewer");
|
|
39
42
|
if (filters.q) params.set("q", filters.q);
|
|
40
43
|
const search = params.toString();
|
|
41
44
|
const query = useInfiniteQuery({
|
|
@@ -150,13 +153,20 @@ export function useReviewItemAction() {
|
|
|
150
153
|
});
|
|
151
154
|
}
|
|
152
155
|
|
|
153
|
-
|
|
156
|
+
/** Newest open Review item title and item count for one waiting Conversation. */
|
|
157
|
+
export type WaitingConversation = { count: number; title: string };
|
|
158
|
+
|
|
159
|
+
const NO_WAITING: ReadonlyMap<string, WaitingConversation> = new Map();
|
|
154
160
|
|
|
155
161
|
/**
|
|
156
|
-
* Return the Conversations that wait on the viewer
|
|
157
|
-
* desk sets this: a linked open action item assigned to the
|
|
162
|
+
* Return the Conversations that wait on the viewer, by Conversation id. Today
|
|
163
|
+
* only the review desk sets this: a linked open action item assigned to the
|
|
164
|
+
* viewer.
|
|
158
165
|
*/
|
|
159
|
-
export function
|
|
166
|
+
export function useWaitingConversations(): ReadonlyMap<
|
|
167
|
+
string,
|
|
168
|
+
WaitingConversation
|
|
169
|
+
> {
|
|
160
170
|
const query = useQuery({
|
|
161
171
|
queryKey: [...REVIEW_ITEMS_QUERY_KEY, "waiting-conversations"],
|
|
162
172
|
queryFn: ({ signal }) =>
|
|
@@ -168,6 +178,23 @@ export function useWaitingConversationIds(): ReadonlySet<string> {
|
|
|
168
178
|
refetchInterval: COUNT_REFRESH_MS,
|
|
169
179
|
retry: false,
|
|
170
180
|
});
|
|
171
|
-
const
|
|
172
|
-
return useMemo(
|
|
181
|
+
const conversations = query.data?.conversations;
|
|
182
|
+
return useMemo(
|
|
183
|
+
() =>
|
|
184
|
+
conversations
|
|
185
|
+
? new Map(
|
|
186
|
+
conversations.map(({ conversationId, count, title }) => [
|
|
187
|
+
conversationId,
|
|
188
|
+
{ count, title },
|
|
189
|
+
]),
|
|
190
|
+
)
|
|
191
|
+
: NO_WAITING,
|
|
192
|
+
[conversations],
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Return the ids of the Conversations that wait on the viewer. */
|
|
197
|
+
export function useWaitingConversationIds(): ReadonlySet<string> {
|
|
198
|
+
const waiting = useWaitingConversations();
|
|
199
|
+
return useMemo(() => new Set(waiting.keys()), [waiting]);
|
|
173
200
|
}
|
package/src/client/types.ts
CHANGED
|
@@ -121,6 +121,8 @@ export type TranscriptViewMessage = {
|
|
|
121
121
|
actorIdentity?: ActorIdentity;
|
|
122
122
|
/** Agent invocation whose input this is. An agent wrote it, not a person. */
|
|
123
123
|
agentInvocationId?: string;
|
|
124
|
+
/** Identity id of the author. Conversation `authors` maps it to the person. */
|
|
125
|
+
actorIdentityId?: string;
|
|
124
126
|
contexts?: TranscriptViewTurnContext[];
|
|
125
127
|
/** Mailbox delivery mode while the message is still pending history commit. */
|
|
126
128
|
delivery?: "defer" | "interrupt";
|
|
@@ -331,7 +331,7 @@ export function createMockReportingApi(): Hono<{
|
|
|
331
331
|
jsonResponse(reviewItemCountSchema, { needsViewer: 0 }),
|
|
332
332
|
);
|
|
333
333
|
app.get("/review-items/waiting-conversations", () =>
|
|
334
|
-
jsonResponse(reviewItemWaitingConversationsSchema, {
|
|
334
|
+
jsonResponse(reviewItemWaitingConversationsSchema, { conversations: [] }),
|
|
335
335
|
);
|
|
336
336
|
app.get("/review-items/:id", () =>
|
|
337
337
|
errorResponse("Review item not found.", 404),
|