Let the lead keep notes on how its user works
This commit is contained in:
@@ -71,6 +71,41 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/me/lead/notes": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/** @description What the calling user's lead agent has noted about how they work, oldest first. The lead keeps them with its remember and forget tools. */
|
||||
get: operations["listLeadNotes"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/me/lead/notes/{noteId}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
noteId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete: operations["deleteLeadNote"];
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/me/focus": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -1236,6 +1271,14 @@ export interface components {
|
||||
tabs: components["schemas"]["TaskTab"][];
|
||||
tab: components["schemas"]["TaskTab"];
|
||||
};
|
||||
LeadNote: {
|
||||
id: string;
|
||||
text: string;
|
||||
/** Format: date-time */
|
||||
created_at: string;
|
||||
/** Format: date-time */
|
||||
updated_at: string;
|
||||
};
|
||||
PaneFocus: {
|
||||
/** @description True while the browser window has focus and the focused element is inside the right pane. */
|
||||
focused: boolean;
|
||||
@@ -1458,6 +1501,47 @@ export interface operations {
|
||||
400: components["responses"]["Error"];
|
||||
};
|
||||
};
|
||||
listLeadNotes: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description The notes. */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["LeadNote"][];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
deleteLeadNote: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
noteId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Deleted. */
|
||||
204: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content?: never;
|
||||
};
|
||||
404: components["responses"]["Error"];
|
||||
};
|
||||
};
|
||||
getFocus: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
@@ -20,6 +20,7 @@ export type Snapshot = Schemas["Snapshot"];
|
||||
export type Participant = Schemas["Participant"];
|
||||
export type Focus = Schemas["Focus"];
|
||||
export type TaskTab = Schemas["TaskTab"];
|
||||
export type LeadNote = Schemas["LeadNote"];
|
||||
|
||||
type Method = "get" | "post" | "put" | "delete";
|
||||
|
||||
|
||||
+72
-5
@@ -1,5 +1,5 @@
|
||||
import { put, type NotificationPrefs } from "./api.js";
|
||||
import { errorText, h, replace, showAlert } from "./dom.js";
|
||||
import { del, get, put, type ByreEvent, type LeadNote, type NotificationPrefs } from "./api.js";
|
||||
import { errorText, h, replace, showAlert, showConfirm } from "./dom.js";
|
||||
import { on, state } from "./state.js";
|
||||
|
||||
const kinds: { key: keyof NotificationPrefs; label: string }[] = [
|
||||
@@ -60,10 +60,77 @@ export function mountSettings(root: HTMLElement): () => void {
|
||||
replace(device, h("p", {}, "This browser doesn't show notifications."), button);
|
||||
};
|
||||
|
||||
replace(root, h("div", { class: "settings-view" }, h("h2", {}, "Notifications"), device, prefs));
|
||||
const off = on("me", renderPrefs);
|
||||
const notes = h("div", { class: "lead-notes" });
|
||||
let loads = 0;
|
||||
const loadNotes = async () => {
|
||||
const n = ++loads;
|
||||
let list: LeadNote[];
|
||||
try {
|
||||
list = await get("/api/me/lead/notes");
|
||||
} catch (err) {
|
||||
replace(notes, h("p", { class: "hint" }, errorText(err)));
|
||||
return;
|
||||
}
|
||||
if (n !== loads) {
|
||||
return;
|
||||
}
|
||||
if (list.length === 0) {
|
||||
replace(notes, h("p", { class: "hint" }, "Your lead hasn't noted anything about how you work yet."));
|
||||
return;
|
||||
}
|
||||
replace(
|
||||
notes,
|
||||
h(
|
||||
"ul",
|
||||
{},
|
||||
...list.map((note) => {
|
||||
const remove = h("button", {}, "delete");
|
||||
remove.onclick = async () => {
|
||||
if (!(await showConfirm([h("p", {}, "Delete this note? Your lead stops applying it."), h("p", {}, note.text)], "Delete", true, remove))) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await del("/api/me/lead/notes/{noteId}", { path: { noteId: note.id } });
|
||||
} catch (err) {
|
||||
void showAlert(errorText(err));
|
||||
}
|
||||
};
|
||||
return h("li", {}, h("span", {}, note.text), remove);
|
||||
}),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
replace(
|
||||
root,
|
||||
h(
|
||||
"div",
|
||||
{ class: "settings-view" },
|
||||
h("h2", {}, "Notifications"),
|
||||
device,
|
||||
prefs,
|
||||
h("h2", {}, "What your lead has learned"),
|
||||
h("p", { class: "hint" }, "Your lead notes your priorities and preferences as it works with you, and starts every session with them."),
|
||||
notes,
|
||||
),
|
||||
);
|
||||
const offs = [
|
||||
on("me", renderPrefs),
|
||||
on("event", (detail) => {
|
||||
const ev = detail as ByreEvent;
|
||||
if (ev.kind === "lead.note_saved" || ev.kind === "lead.note_deleted") {
|
||||
void loadNotes();
|
||||
}
|
||||
}),
|
||||
];
|
||||
renderPrefs();
|
||||
renderDevice();
|
||||
void loadNotes();
|
||||
|
||||
return off;
|
||||
return () => {
|
||||
loads++;
|
||||
for (const off of offs) {
|
||||
off();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user