Skip to content

feat: filter tasks that are waiting for user input - #19377

Merged
BrunoQuaresma merged 20 commits into
mainfrom
bq/19324
Aug 21, 2025
Merged

BrunoQuaresma merged 20 commits into
mainfrom
bq/19324

Conversation

@BrunoQuaresma

Copy link
Copy Markdown
Contributor

Closes #19324

Screenshot 2025-08-15 at 14 45 39

@BrunoQuaresma
BrunoQuaresma requested a review from a team August 15, 2025 17:56
@BrunoQuaresma BrunoQuaresma self-assigned this Aug 15, 2025
@BrunoQuaresma
BrunoQuaresma requested review from aqandrew and removed request for a team August 15, 2025 17:56
@BrunoQuaresma
BrunoQuaresma requested a review from aslilac as a code owner August 15, 2025 17:56
Comment on lines +5 to +6
// TODO: This is a temporary solution while the BE does not return the Task in a
// right shape with a custom name. This should be removed once the BE is fixed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnstcn johnstcn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but deferring approval to FE domain experts.

Comment thread site/src/api/api.ts Resolved
Comment thread site/src/api/api.ts Resolved
Comment thread site/src/api/api.ts Resolved
value?: string;
};

function useUsersOptions({ query, value }: UseUsersOptionsOptions) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't really need to be a hook imo. it should be a query function like we generally use, and it can take user as an argument.

@BrunoQuaresma BrunoQuaresma Aug 19, 2025 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, but IMO, it encapsulates the intention quite well and improve the readability. It makes easier for me to know where and for what things are being used for. Eg. It is clear for me for what the useQuery and usesAuthenticated are being used for.

Unfortunately, you can't use hooks inside of regular functions, but I'm happy to change the code to use any existent convention.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the entirety of this hook except for const { user } = useAuthenticated(); can be encapsulated in a query options function tho! and that better matches how we do it everywhere else.

Unfortunately, you can't use hooks inside of regular functions

and this is part of why I am so against custom hooks in 90% of use cases. they're viral function coloring, and should be avoided unless they are actually necessary to encapsulate stateful logic. I don't think that's the case here, as all of the logic is independent of the state.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the new React docs on custom hooks are very insightful. Even they don't think people should really be making custom hooks most of the time!

https://react.dev/learn/reusing-logic-with-custom-hooks#there-is-more-than-one-way-to-do-it

Comment thread site/src/pages/TasksPage/TasksPage.tsx Resolved
Comment thread site/src/pages/TasksPage/TasksPage.tsx Resolved
Comment on lines +7 to +26
export const data = {
async createTask(
prompt: string,
userId: string,
templateVersionId: string,
presetId: string | undefined,
): Promise<Task> {
const workspace = await API.experimental.createTask(userId, {
name: `task-${generateWorkspaceName()}`,
template_version_id: templateVersionId,
template_version_preset_id: presetId,
prompt,
});

return {
workspace,
prompt,
};
},
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the need for this data wrapper. why not just export the function directly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of some spyOn limitations 😢. I'm not able to make it work when doing the following:

import * as data from "./data"
spyOn(data, "createTask")
Cannot spy on export "createTask". Module namespace is not configurable in ESM. See: https://vitest.dev/guide/browser/#limitations

But it should be temporary, since the create task API should handle that.

Comment thread site/src/pages/TasksPage/data.ts Resolved
};

const sortSelectedFirst = (a: User) =>
value && a.username === value ? -1 : 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't hand the case where a.username === a.username

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I got it 🤔

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't even blame you, writing sorting functions is really unintuitive. 😅

if a.username === a.username and a.username === value you'll still return -1 when you should return 0. they're both the selected user, so you shouldn't be preferring one over the other. although I guess saying it out loud, that case probably won't ever come up except maybe in tests that don't generate unique usernames.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be ok if we let this as it is?

Bruno Quaresma and others added 2 commits August 19, 2025 08:54
@BrunoQuaresma
BrunoQuaresma requested review from aslilac and removed request for aqandrew August 19, 2025 12:17
Comment thread site/src/pages/TasksPage/data.ts Resolved
Comment on lines +180 to +194
const [firstTask, ...otherTasks] = MockTasks;
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockResolvedValue([
{
...firstTask,
workspace: {
...firstTask.workspace,
latest_app_status: {
...firstTask.workspace.latest_app_status,
state: "idle" as const,
},
},
},
...otherTasks,
]);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be a nice opportunity to use structuredClone to mask some noise:

Suggested change
const [firstTask, ...otherTasks] = MockTasks;
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API.experimental, "getTasks").mockResolvedValue([
{
...firstTask,
workspace: {
...firstTask.workspace,
latest_app_status: {
...firstTask.workspace.latest_app_status,
state: "idle" as const,
},
},
},
...otherTasks,
]);
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
const tasks = structuredClone(MockTasks);
tasks[0].workspace.latest_app_status.state = "idle";
spyOn(API.experimental, "getTasks").mockResolvedValue(tasks);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue with that, structuredClone keep the read only structure causing an TS error.

Cannot assign to 'state' because it is a read-only property.

Comment thread .vscode/settings.json Resolved
Comment thread site/src/api/api.ts Resolved
Comment on lines +202 to +214
spyOn(API.experimental, "getTasks").mockResolvedValue([
{
...firstTask,
workspace: {
...firstTask.workspace,
latest_app_status: {
...firstTask.workspace.latest_app_status,
state: "idle" as const,
},
},
// biome-ignore lint/suspicious/noExplicitAny: Testing malformed data edge cases
] as any;
},
...otherTasks,
]);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the same applies here

Comment thread site/src/pages/TasksPage/TasksPage.tsx Outdated
);
}

const PillButton = ({ className, active, ...props }: PillButtonProps) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FC?

also, seems like a good candidate for a general component. might be worth moving to components/.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like a good candidate for a general component.

Wdyt about waiting for more use cases using it?

Comment thread site/src/pages/TasksPage/TasksTable.tsx Resolved
};

const sortSelectedFirst = (a: User) =>
value && a.username === value ? -1 : 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't even blame you, writing sorting functions is really unintuitive. 😅

if a.username === a.username and a.username === value you'll still return -1 when you should return 0. they're both the selected user, so you shouldn't be preferring one over the other. although I guess saying it out loud, that case probably won't ever come up except maybe in tests that don't generate unique usernames.

@BrunoQuaresma

Copy link
Copy Markdown
Contributor Author

@aslilac hooks refactored and other requests added. ✅

@johnstcn johnstcn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending FE approval.

@BrunoQuaresma
BrunoQuaresma merged commit d77c3d0 into main Aug 21, 2025
@BrunoQuaresma
BrunoQuaresma deleted the bq/19324 branch August 21, 2025 18:06
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tasks: Filter tasks that are waiting for user input

3 participants