mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site): hide slash skills menu when user has no personal skills (#26953)
This commit is contained in:
@@ -79,10 +79,26 @@ export const EmptySkills: Story = {
|
||||
},
|
||||
play: async ({ canvasElement, args }) => {
|
||||
const editor = await typeInEditor(canvasElement, "/");
|
||||
expect(await findVisibleText("No personal skills found.")).toBeDefined();
|
||||
// "/" is plain text when the skills list is empty.
|
||||
expectNoVisibleTextImmediately("No personal skills found.");
|
||||
await userEvent.keyboard("{Enter}");
|
||||
expect(args.onEnter).toHaveBeenCalledTimes(1);
|
||||
expect(editor.textContent).toBe("/");
|
||||
},
|
||||
};
|
||||
|
||||
export const FilteredEmptyKeepsMenuOpen: Story = {
|
||||
args: {
|
||||
onEnter: fn(),
|
||||
},
|
||||
play: async ({ canvasElement, args }) => {
|
||||
const editor = await typeInEditor(canvasElement, "/zzzz");
|
||||
expect(
|
||||
await findVisibleText("No personal skills match that query."),
|
||||
).toBeDefined();
|
||||
await userEvent.keyboard("{Enter}");
|
||||
expect(args.onEnter).not.toHaveBeenCalled();
|
||||
expect(editor.textContent).toBe("/");
|
||||
expect(editor.textContent).toBe("/zzzz");
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -595,12 +595,25 @@ const ChatMessageInput = ({
|
||||
useState<ActiveSkillsTrigger | null>(null);
|
||||
const suppressedSkillsTriggerRef = useRef<SkillsTriggerLocation | null>(null);
|
||||
const [skillsMenuSelectedIndex, setSkillsMenuSelectedIndex] = useState(0);
|
||||
const skillsMenuOpen = Boolean(skillsTrigger);
|
||||
const hasSkillsTrigger = Boolean(skillsTrigger);
|
||||
const hasPersonalSkillsOverride = personalSkillsOverride !== undefined;
|
||||
const skillsQuery = useQuery({
|
||||
...userSkills(),
|
||||
enabled: skillsMenuOpen && personalSkillsOverride === undefined,
|
||||
enabled: hasSkillsTrigger && !hasPersonalSkillsOverride,
|
||||
// Avoid refetching on each trigger toggle from caret movement.
|
||||
staleTime: 60_000,
|
||||
});
|
||||
const personalSkills = personalSkillsOverride ?? skillsQuery.data ?? [];
|
||||
// A stale empty cache with a refetch in flight must not dismiss the menu.
|
||||
const isResolvedEmptySkillsList = hasPersonalSkillsOverride
|
||||
? personalSkills.length === 0
|
||||
: skillsQuery.isSuccess &&
|
||||
!skillsQuery.isFetching &&
|
||||
personalSkills.length === 0;
|
||||
// When the loaded skills list is empty, "/" is plain text. When only
|
||||
// the filtered result is empty, keep the menu open for the no-match
|
||||
// message.
|
||||
const skillsMenuOpen = hasSkillsTrigger && !isResolvedEmptySkillsList;
|
||||
const filteredPersonalSkills = skillsTrigger
|
||||
? filterPersonalSkills(personalSkills, skillsTrigger.query)
|
||||
: [];
|
||||
@@ -890,7 +903,11 @@ const ChatMessageInput = ({
|
||||
anchorRect={skillsTrigger?.anchorRect ?? null}
|
||||
query={skillsTrigger?.query ?? ""}
|
||||
skills={filteredPersonalSkills}
|
||||
isLoading={skillsMenuOpen && skillsQuery.isLoading}
|
||||
isLoading={
|
||||
skillsMenuOpen &&
|
||||
personalSkills.length === 0 &&
|
||||
skillsQuery.isFetching
|
||||
}
|
||||
onSelectedIndexChange={setSkillsMenuSelectedIndex}
|
||||
isError={skillsMenuOpen && skillsQuery.isError}
|
||||
selectedIndex={selectedSkillIndex}
|
||||
|
||||
Reference in New Issue
Block a user