Skip to content

Commit 4392747

Browse files
committed
feat: enhance DNamespaceProject components with minimized state and improved project selection
1 parent 50d6c28 commit 4392747

File tree

3 files changed

+82
-60
lines changed

3 files changed

+82
-60
lines changed
Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,91 @@
11
import {Code0Component, useService} from "../../utils";
2-
import {NamespaceProject, Organization, User} from "@code0-tech/sagittarius-graphql-types";
2+
import {NamespaceProject} from "@code0-tech/sagittarius-graphql-types";
33
import React from "react";
44
import {Flex} from "../flex/Flex";
5-
import {DNamespaceReactiveService} from "../d-namespace";
6-
import {DOrganizationReactiveService, DOrganizationView} from "../d-organization";
7-
import {DUserReactiveService, DUserView} from "../d-user";
85
import {DNamespaceProjectReactiveService} from "./DNamespaceProject.service";
96
import {Avatar} from "../avatar/Avatar";
107
import {Text} from "../text/Text";
118
import {Badge} from "../badge/Badge";
12-
import {IconGitFork, IconServer, IconServerSpark, IconSettings} from "@tabler/icons-react";
9+
import {IconEdit, IconGitFork, IconServer, IconServerSpark} from "@tabler/icons-react";
1310
import {DRuntimeReactiveService} from "../d-runtime";
1411
import {Button} from "../button/Button";
1512
import {DNamespaceProjectView} from "./DNamespaceProject.view";
1613

1714
export interface DNamespaceProjectContentProps extends Code0Component<HTMLDivElement> {
1815
projectId: NamespaceProject["id"]
1916
onSetting?: (project: DNamespaceProjectView) => void
17+
minimized?: boolean
2018
}
2119

2220
export const DNamespaceProjectContent: React.FC<DNamespaceProjectContentProps> = (props) => {
2321

2422
const {
2523
projectId,
2624
onSetting = () => {
27-
}
25+
},
26+
minimized = false
2827
} = props
2928
const projectService = useService(DNamespaceProjectReactiveService)
30-
const runtimeService = useService(DRuntimeReactiveService)
29+
const runtimeService = !minimized ? useService(DRuntimeReactiveService) : null
3130

3231
const project = React.useMemo(() => projectService.getById(projectId), [projectService, projectId])
33-
const assignedRuntime = React.useMemo(() => project ? runtimeService.getById(project.primaryRuntime?.id) : null, [project])
32+
const assignedRuntime = !minimized ? React.useMemo(() => project ? runtimeService!!.getById(project.primaryRuntime?.id) : null, [project]) : null
3433

3534
return (
3635
<Flex align={"center"} style={{gap: "1.3rem"}} justify={"space-between"}>
37-
<Flex align={"center"} style={{gap: "1.3rem"}}>
36+
<Flex align={"center"} style={{gap: "0.7rem"}}>
3837
<Avatar bg={"transparent"}
3938
identifier={project?.name ?? ""}/>
4039
<Flex style={{flexDirection: "column", gap: "0.35rem"}}>
41-
<Text size={"lg"} hierarchy={"primary"} display={"block"}>
40+
<Text size={!minimized ? "md" : "xs"} hierarchy={"secondary"}
41+
display={"block"}>
4242
{project?.name}
4343
</Text>
44-
<Text size={"sm"} hierarchy={"tertiary"} display={"block"}>
44+
<Text size={!minimized ? "sm" : "xs"} hierarchy={"tertiary"} display={"block"}>
4545
{project?.description}
4646
</Text>
4747
</Flex>
4848
</Flex>
49-
<Flex align={"center"} style={{gap: "1.3rem"}}>
50-
<Flex align={"center"} style={{gap: "0.35rem", flexWrap: "wrap"}}>
51-
{/* Flow count */}
52-
<Badge color={"secondary"}>
53-
<IconGitFork size={16}/>
54-
<Text size={"xs"}>
55-
{project?.flows?.count ?? 0}
49+
{!minimized ? (
50+
<Flex align={"center"} style={{gap: "1.3rem"}}>
51+
<Flex style={{flexDirection: "column", gap: "0.35rem"}}>
52+
<Text size="xs" hierarchy="tertiary">
53+
Usage
5654
</Text>
57-
</Badge>
58-
{/* Runtime Count */}
59-
<Badge color={"secondary"}>
60-
<IconServer size={16}/>
61-
<Text size={"xs"}>
62-
{project?.runtimes?.count ?? 0}
63-
</Text>
64-
</Badge>
65-
{/* Assigned Runtime */}
66-
{assignedRuntime && (
67-
<Badge color={"secondary"}>
68-
<IconServerSpark size={16}/>
69-
<Text size={"xs"}>{assignedRuntime.name}</Text>
70-
</Badge>
71-
)}
55+
<Flex align={"center"} style={{gap: "0.35rem", flexWrap: "wrap"}}>
56+
{/* Flow count */}
57+
<Badge border>
58+
<IconGitFork size={16}/>
59+
<Text size={"xs"}>
60+
{project?.flows?.count ?? 0}
61+
</Text>
62+
</Badge>
63+
{/* Runtime Count */}
64+
<Badge border>
65+
<IconServer size={16}/>
66+
<Text size={"xs"}>
67+
{project?.runtimes?.count ?? 0}
68+
</Text>
69+
</Badge>
70+
{/* Assigned Runtime */}
71+
{assignedRuntime && (
72+
<Badge border>
73+
<IconServerSpark size={16}/>
74+
<Text size={"xs"}>{assignedRuntime.name}</Text>
75+
</Badge>
76+
)}
77+
</Flex>
78+
</Flex>
79+
{project?.userAbilities?.deleteNamespaceProject || project?.userAbilities?.updateNamespaceProject ? (
80+
<Button color={"secondary"} variant={"filled"} onClick={(event) => {
81+
event.stopPropagation()
82+
onSetting(project)
83+
}}>
84+
<IconEdit size={16}/>
85+
</Button>
86+
) : null}
7287
</Flex>
73-
{project?.userAbilities?.deleteNamespaceProject || project?.userAbilities?.updateNamespaceProject ? (
74-
<Button color={"secondary"} onClick={(event) => {
75-
event.stopPropagation()
76-
onSetting(project)
77-
}}>
78-
<IconSettings size={16}/>
79-
</Button>
80-
) : null}
81-
</Flex>
88+
) : null}
8289
</Flex>
8390
)
8491
}

src/components/d-project/DNamespaceProjectMenu.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const DProjectMenuExample: DNamespaceProjectMenuStory = {
6262
createdAt: new Date().toString(),
6363
updatedAt: new Date().toString(),
6464
namespace: {
65-
id: "gid://sagittarius/Namespace/1"
65+
id: "gid://sagittarius/Namespace/2"
6666
},
6767
flow: undefined,
6868
flows: undefined,
@@ -76,6 +76,7 @@ export const DProjectMenuExample: DNamespaceProjectMenuStory = {
7676
{React.useMemo(() => {
7777
return (
7878
<DNamespaceProjectMenu
79+
namespaceId={"gid://sagittarius/Namespace/1"}
7980
projectId={"gid://sagittarius/NamespaceProject/1"}
8081
onProjectSelect={props.onProjectSelect}
8182
/>

src/components/d-project/DNamespaceProjectMenu.tsx

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,54 @@
11
"use client"
22

33
import React from "react"
4-
import {Menu, MenuContent, MenuItem, MenuPortal, MenuProps, MenuTrigger} from "../menu/Menu"
4+
import {Menu, MenuContent, MenuItem, MenuPortal, MenuProps, MenuSeparator, MenuTrigger} from "../menu/Menu"
55
import {DNamespaceProjectReactiveService} from "./DNamespaceProject.service"
66
import {useService} from "../../utils/contextStore"
7-
import {Scalars} from "@code0-tech/sagittarius-graphql-types"
7+
import {Namespace, Scalars} from "@code0-tech/sagittarius-graphql-types"
88
import {Button} from "../button/Button"
9+
import {DNamespaceProjectView} from "./DNamespaceProject.view";
10+
import {DNamespaceProjectContent} from "./DNamespaceProjectContent";
911

1012
export interface DNamespaceProjectMenuProps extends MenuProps {
11-
projectId: Scalars['NamespaceProjectID']['output']
12-
onProjectSelect: (id: Scalars['NamespaceProjectID']['output']) => void
13+
onProjectSelect: (project: DNamespaceProjectView) => void
14+
namespaceId: Namespace["id"]
15+
filter?: (project: DNamespaceProjectView, index: number) => boolean
16+
projectId?: Scalars['NamespaceProjectID']['output']
17+
children?: React.ReactNode
1318
}
1419

1520
const DNamespaceProjectMenu: React.FC<DNamespaceProjectMenuProps> = props => {
21+
22+
const {onProjectSelect, namespaceId, filter = () => true, projectId, children} = props
23+
1624
const projectService = useService(DNamespaceProjectReactiveService)
1725
const projectStore = useService(DNamespaceProjectReactiveService)
18-
const currentProject = projectService.getById(props.projectId)
26+
const currentProject = projectService.getById(projectId)
27+
const projects = React.useMemo(() => projectService.values({namespaceId: namespaceId}).filter(filter), [projectStore, namespaceId])
1928

2029
return React.useMemo(() => {
2130
return (
2231
<Menu {...props}>
2332
<MenuTrigger asChild>
24-
<Button variant={"none"} style={{background: "transparent"}}>
25-
{currentProject?.name}
26-
</Button>
33+
{children ? children : (
34+
<Button variant={"none"} paddingSize={"xxs"}>
35+
{currentProject?.name}
36+
</Button>
37+
)}
2738
</MenuTrigger>
2839
<MenuPortal>
29-
<MenuContent side={"bottom"} align={"start"} sideOffset={0}>
30-
{projectService.values().map((project) => (
31-
<MenuItem
32-
key={project.id}
33-
onSelect={() => props.onProjectSelect(project.id!!)}
34-
>
35-
{project.name}
36-
</MenuItem>
37-
))}
40+
<MenuContent side={"bottom"} align={"center"} sideOffset={8} maw={"200px"}>
41+
{projects.map((project, index) => (
42+
<>
43+
<MenuItem
44+
key={project.id}
45+
onSelect={() => onProjectSelect(project)}
46+
>
47+
<DNamespaceProjectContent minimized projectId={project.id}/>
48+
</MenuItem>
49+
{index < projects.length - 1 && <MenuSeparator/>}
50+
</>
51+
))}
3852
</MenuContent>
3953
</MenuPortal>
4054
</Menu>

0 commit comments

Comments
 (0)