Give every task a bot: drop shared workspace tasks
A workspace task with no bot was seen by every bot working there. Now a task can't be saved without a bot, a worker reaches only its own (the workspace admin and the coordinator still reach all), the workspace page picks who has a new task, and a bot leaving a workspace or deleted passes its tasks there to the workspace's admin bot, else the coordinator (also at boot for rows without a bot). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -15,7 +15,7 @@ type Params = {
|
||||
|
||||
/**
|
||||
* A conversation's tasks: a bot's own list, or in a workspace the ones it
|
||||
* has there plus the shared ones nobody has yet. Loaded on open and refreshed after every change,
|
||||
* has there. Loaded on open and refreshed after every change,
|
||||
* never part of the page props.
|
||||
*/
|
||||
export default function useBotTasks({ bot_id, workspace_id, enabled = true }: Params) {
|
||||
|
||||
@@ -31,7 +31,7 @@ type Props = {
|
||||
|
||||
/**
|
||||
* The tasks this conversation works on: a bot's own list, or in a workspace
|
||||
* the ones it has there plus the shared ones nobody has yet. Open it from the header menu; the list loads
|
||||
* the ones it has there. Open it from the header menu; the list loads
|
||||
* then, so the page's props stay small. A crew manager adds, moves, edits
|
||||
* and deletes; a card opens the task in a modal of its own with everything
|
||||
* about it.
|
||||
@@ -157,7 +157,7 @@ export default function BotTasksModal({ bot, workspace, menu, on_open }: Props)
|
||||
</Row>
|
||||
<Span className="text-[13px] leading-[18px] text-ink-secondary">
|
||||
{workspace?.id
|
||||
? `What ${name} has in ${workspace.name || "this workspace"}, and the shared tasks there nobody has taken up yet. The workspace shows every bot's.`
|
||||
? `What ${name} has in ${workspace.name || "this workspace"}. The workspace shows every bot's.`
|
||||
: `What ${name} is working through, and what it's waiting on.`}
|
||||
</Span>
|
||||
</Stack>
|
||||
|
||||
@@ -22,14 +22,19 @@ type Props = {
|
||||
* Its tasks, open first.
|
||||
*/
|
||||
tasks: TaskWithNames[];
|
||||
/**
|
||||
* The bots working there, to pick who has a new task.
|
||||
*/
|
||||
bots: { id?: number | string | null; name?: string | null }[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Every task in a workspace, whichever bot has it (or shared, nobody's
|
||||
* yet). Each bot there sees its own and the shared ones. Add and change one by hand here; the bots
|
||||
* Every task in a workspace, whichever bot has it: every task belongs to
|
||||
* one bot, which sees only its own (the workspace's admin bot sees all).
|
||||
* Add and change one by hand here; the bots
|
||||
* keep it up to date themselves as they work.
|
||||
*/
|
||||
export default function WorkspaceTasksGroup({ workspace_id, tasks }: Props) {
|
||||
export default function WorkspaceTasksGroup({ workspace_id, tasks, bots }: Props) {
|
||||
const { pageProps } = useContext(AppContext);
|
||||
const [items, setItems] = useState(tasks);
|
||||
const [busy, setBusy] = useState(false);
|
||||
@@ -89,18 +94,19 @@ export default function WorkspaceTasksGroup({ workspace_id, tasks }: Props) {
|
||||
<SettingsGroup
|
||||
id="tasks"
|
||||
title="Tasks"
|
||||
description="Every task in this workspace, whichever bot has it. A bot sees its own here and the shared ones nobody has taken up yet."
|
||||
description="Every task in this workspace, whichever bot has it. Each bot sees only its own; the workspace's admin bot and the coordinator see them all."
|
||||
>
|
||||
<Stack className="w-full gap-2! items-stretch">
|
||||
{can_manage ? (
|
||||
<Row className="justify-end">
|
||||
<Button
|
||||
title="Add a task"
|
||||
title={bots.length ? "Add a task" : "Add a bot to this workspace first"}
|
||||
type="button"
|
||||
variant="outlined"
|
||||
color="gray"
|
||||
size="small"
|
||||
onClick={() => setAdding(true)}
|
||||
disabled={!bots.length}
|
||||
>
|
||||
Add task
|
||||
</Button>
|
||||
@@ -138,10 +144,11 @@ export default function WorkspaceTasksGroup({ workspace_id, tasks }: Props) {
|
||||
open={adding}
|
||||
setOpen={setAdding}
|
||||
title="Add a task"
|
||||
description="It's added shared: whichever bot here takes it up has it. Hand it over to give it to one."
|
||||
description="Pick the bot that has it. Hand it over later to give it to another."
|
||||
>
|
||||
<TaskForm
|
||||
workspace_id={workspace_id}
|
||||
bots={bots}
|
||||
onCancel={() => setAdding(false)}
|
||||
onSaved={(task, msg) => {
|
||||
replace({ task });
|
||||
|
||||
@@ -42,6 +42,7 @@ export default function WorkspaceDashboard() {
|
||||
<WorkspaceTasksGroup
|
||||
workspace_id={workspace_id}
|
||||
tasks={pageProps?.workspace_tasks || []}
|
||||
bots={pageProps?.workspace_bots || []}
|
||||
/>
|
||||
<WorkspaceActivityGroup
|
||||
workspace_id={workspace_id}
|
||||
|
||||
@@ -6,8 +6,8 @@ import type { APIResponseObject, BunextAPIRouteHandler } from "@moduletrace/bune
|
||||
|
||||
/**
|
||||
* The user's tasks: a bot's own list (`?bot_id=`), a workspace's
|
||||
* (`?workspace_id=`), one bot's there with the unassigned ones
|
||||
* (`?workspace_id=&bot_id=`), or every task they reach. `?status=` narrows to one
|
||||
* (`?workspace_id=`), one bot's there (`?workspace_id=&bot_id=`), or every
|
||||
* task they reach. `?status=` narrows to one
|
||||
* status, `?open=1` to the open ones.
|
||||
*/
|
||||
export const handler: BunextAPIRouteHandler<APIResponseObject<TaskWithNames>> = async ({ req }) => {
|
||||
@@ -33,7 +33,6 @@ export const handler: BunextAPIRouteHandler<APIResponseObject<TaskWithNames>> =
|
||||
payload: await grabTasks({
|
||||
user_id: user.id,
|
||||
only_bot_id: bot_id,
|
||||
with_unassigned: Boolean(bot_id && workspace_id),
|
||||
only_workspace_id: workspace_id,
|
||||
own_list: Boolean(bot_id && !workspace_id),
|
||||
statuses: status ? [status] : undefined,
|
||||
|
||||
@@ -11,8 +11,8 @@ import safeErrorMessage from "@/src/utils/safe-error-message";
|
||||
import type { APIResponseObject, BunextAPIRouteHandler } from "@moduletrace/bunext/types";
|
||||
|
||||
/**
|
||||
* Adds a task to a bot's list (`bot_id`), a workspace (`workspace_id`,
|
||||
* shared) or a bot in a workspace (both), or changes one (`task_id`). Returns the task with its
|
||||
* Adds a task to a bot's list (`bot_id`) or a bot's in a workspace (with
|
||||
* `workspace_id`), or changes one (`task_id`). Returns the task with its
|
||||
* notes and files.
|
||||
*/
|
||||
export const handler: BunextAPIRouteHandler<APIResponseObject<TaskDetail>> = async ({ req, body }) => {
|
||||
|
||||
Reference in New Issue
Block a user