• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

stacklok / codegate-ui / 12869295651

20 Jan 2025 01:39PM UTC coverage: 66.696% (-1.2%) from 67.945%
12869295651

push

github

web-flow
feat: enable toggle workspace, invalidate on workspace update (#130)

* feat: enable toggle workspace, invalidate on workspace update

* fix: failing tests

* fix(workspaces selection): checkbox & bg color

252 of 459 branches covered (54.9%)

Branch coverage included in aggregate %.

12 of 35 new or added lines in 7 files covered. (34.29%)

7 existing lines in 1 file now uncovered.

507 of 679 relevant lines covered (74.67%)

54.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.0
/src/features/workspace/components/workspaces-selection.tsx
1
import { useListWorkspaces } from "@/features/workspace/hooks/use-list-workspaces";
2
import {
3
  Button,
4
  DialogTrigger,
5
  Input,
6
  LinkButton,
7
  ListBox,
8
  ListBoxItem,
9
  Popover,
10
  SearchField,
11
  Separator,
12
} from "@stacklok/ui-kit";
13
import { useQueryClient } from "@tanstack/react-query";
14
import { ChevronDown, Search, Settings } from "lucide-react";
15
import { useState } from "react";
16
import { useActiveWorkspaces } from "../hooks/use-active-workspaces";
17
import { useActivateWorkspace } from "../hooks/use-activate-workspace";
18
import clsx from "clsx";
19

20
export function WorkspacesSelection() {
21
  const queryClient = useQueryClient();
4✔
22

23
  const { data: workspacesResponse } = useListWorkspaces();
4✔
24
  const { data: activeWorkspacesResponse } = useActiveWorkspaces();
4✔
25
  const { mutateAsync: activateWorkspace } = useActivateWorkspace();
4✔
26

27
  const activeWorkspaceName: string | null =
28
    activeWorkspacesResponse?.workspaces[0]?.name ?? null;
4✔
29

30
  const [isOpen, setIsOpen] = useState(false);
4✔
31
  const [searchWorkspace, setSearchWorkspace] = useState("");
4✔
32
  const workspaces = workspacesResponse?.workspaces ?? [];
4✔
33
  const filteredWorkspaces = workspaces.filter((workspace) =>
4✔
UNCOV
34
    workspace.name.toLowerCase().includes(searchWorkspace.toLowerCase()),
×
35
  );
36

37
  const handleWorkspaceClick = (name: string) => {
4✔
NEW
UNCOV
38
    activateWorkspace({ body: { name } }).then(() => {
×
NEW
UNCOV
39
      queryClient.invalidateQueries({ refetchType: "all" });
×
NEW
UNCOV
40
      setIsOpen(false);
×
41
    });
42
  };
43

44
  return (
UNCOV
45
    <DialogTrigger isOpen={isOpen} onOpenChange={(test) => setIsOpen(test)}>
×
46
      <Button variant="tertiary" className="flex cursor-pointer">
47
        Workspace {activeWorkspaceName ?? "default"}
8✔
48
        <ChevronDown />
49
      </Button>
50

51
      <Popover className="w-1/4 p-4" placement="bottom left">
52
        <div>
53
          <div>
54
            <SearchField
55
              onChange={setSearchWorkspace}
56
              autoFocus
57
              aria-label="search"
58
            >
59
              <Input icon={<Search />} />
60
            </SearchField>
61
          </div>
62

63
          <ListBox
64
            aria-label="Workspaces"
65
            items={filteredWorkspaces}
66
            selectedKeys={activeWorkspaceName ? [activeWorkspaceName] : []}
4!
67
            onAction={(v) => {
NEW
UNCOV
68
              handleWorkspaceClick(v?.toString());
×
69
            }}
70
            className="py-2 pt-3"
71
            renderEmptyState={() => (
72
              <p className="text-center">No workspaces found</p>
73
            )}
74
          >
75
            {(item) => (
76
              <ListBoxItem
77
                id={item.name}
78
                key={item.name}
79
                data-is-selected={item.name === activeWorkspaceName}
80
                className={clsx(
81
                  "cursor-pointer py-2 m-1 text-base hover:bg-gray-300",
82
                  {
83
                    "!bg-gray-900 hover:bg-gray-900 !text-gray-25 hover:!text-gray-25":
84
                      item.is_active,
85
                  },
86
                )}
87
              >
88
                {item.name}
89
              </ListBoxItem>
90
            )}
91
          </ListBox>
92
          <Separator className="" />
93
          <LinkButton
94
            href="/workspaces"
NEW
UNCOV
95
            onPress={() => setIsOpen(false)}
×
96
            variant="tertiary"
97
            className="text-secondary h-8 pl-2 gap-2 flex mt-2 justify-start"
98
          >
99
            <Settings />
100
            Manage Workspaces
101
          </LinkButton>
102
        </div>
103
      </Popover>
104
    </DialogTrigger>
105
  );
106
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc