-
Notifications
You must be signed in to change notification settings - Fork 11
fix: Release channel ui cleanup #188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| "use client"; | ||
|
|
||
| import React, { useState } from "react"; | ||
| import React from "react"; | ||
| import { useParams, useRouter, useSearchParams } from "next/navigation"; | ||
| import { | ||
| IconDotsVertical, | ||
|
|
@@ -21,11 +21,38 @@ import { EditFilterForm } from "./Filter"; | |
| import { Overview } from "./Overview"; | ||
| import { ReleaseChannels } from "./ReleaseChannels"; | ||
|
|
||
| export enum EnvironmentDrawerTab { | ||
| Overview = "overview", | ||
| Targets = "targets", | ||
| ReleaseChannels = "release-channels", | ||
| } | ||
|
|
||
| const tabParam = "tab"; | ||
| const useEnvironmentDrawerTab = () => { | ||
| const router = useRouter(); | ||
| const params = useSearchParams(); | ||
| const tab = params.get(tabParam); | ||
|
|
||
| const setTab = (tab: EnvironmentDrawerTab | null) => { | ||
| const url = new URL(window.location.href); | ||
| if (tab === null) { | ||
| url.searchParams.delete(tabParam); | ||
| router.replace(`${url.pathname}?${url.searchParams.toString()}`); | ||
| return; | ||
| } | ||
| url.searchParams.set(tabParam, tab); | ||
| router.replace(`${url.pathname}?${url.searchParams.toString()}`); | ||
| }; | ||
|
|
||
| return { tab, setTab }; | ||
| }; | ||
|
|
||
| const param = "environment_id"; | ||
| export const useEnvironmentDrawer = () => { | ||
| const router = useRouter(); | ||
| const params = useSearchParams(); | ||
| const environmentId = params.get(param); | ||
| const { tab, setTab } = useEnvironmentDrawerTab(); | ||
|
|
||
| const setEnvironmentId = (id: string | null) => { | ||
| const url = new URL(window.location.href); | ||
|
|
@@ -38,13 +65,17 @@ export const useEnvironmentDrawer = () => { | |
| router.replace(`${url.pathname}?${url.searchParams.toString()}`); | ||
| }; | ||
|
|
||
| const removeEnvironmentId = () => setEnvironmentId(null); | ||
| const removeEnvironmentId = () => { | ||
| setTab(null); | ||
| setEnvironmentId(null); | ||
| }; | ||
|
|
||
| return { environmentId, setEnvironmentId, removeEnvironmentId }; | ||
| return { environmentId, setEnvironmentId, removeEnvironmentId, tab, setTab }; | ||
| }; | ||
|
|
||
| export const EnvironmentDrawer: React.FC = () => { | ||
| const { environmentId, removeEnvironmentId } = useEnvironmentDrawer(); | ||
| const { environmentId, removeEnvironmentId, tab, setTab } = | ||
| useEnvironmentDrawer(); | ||
| const isOpen = Boolean(environmentId); | ||
| const setIsOpen = removeEnvironmentId; | ||
| const environmentQ = api.environment.byId.useQuery(environmentId ?? "", { | ||
|
|
@@ -65,8 +96,6 @@ export const EnvironmentDrawer: React.FC = () => { | |
| ); | ||
| const deployments = deploymentsQ.data; | ||
|
|
||
| const [activeTab, setActiveTab] = useState("overview"); | ||
|
|
||
| const loading = | ||
| environmentQ.isLoading || workspaceQ.isLoading || deploymentsQ.isLoading; | ||
|
|
||
|
|
@@ -107,42 +136,43 @@ export const EnvironmentDrawer: React.FC = () => { | |
| <div className="flex w-full gap-6 p-6"> | ||
| <div className="space-y-1"> | ||
| <TabButton | ||
| active={activeTab === "overview"} | ||
| onClick={() => setActiveTab("overview")} | ||
| active={tab === EnvironmentDrawerTab.Overview || tab == null} | ||
| onClick={() => setTab(EnvironmentDrawerTab.Overview)} | ||
| icon={<IconInfoCircle className="h-4 w-4" />} | ||
| label="Overview" | ||
| /> | ||
| <TabButton | ||
| active={activeTab === "targets"} | ||
| onClick={() => setActiveTab("targets")} | ||
| active={tab === EnvironmentDrawerTab.Targets} | ||
| onClick={() => setTab(EnvironmentDrawerTab.Targets)} | ||
| icon={<IconTarget className="h-4 w-4" />} | ||
| label="Targets" | ||
| /> | ||
| <TabButton | ||
| active={activeTab === "release-channels"} | ||
| onClick={() => setActiveTab("release-channels")} | ||
| active={tab === EnvironmentDrawerTab.ReleaseChannels} | ||
| onClick={() => setTab(EnvironmentDrawerTab.ReleaseChannels)} | ||
| icon={<IconFilter className="h-4 w-4" />} | ||
| label="Release Channels" | ||
|
Comment on lines
+139
to
154
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider extracting tab configuration to reduce repetition. The tab button definitions follow a repetitive pattern that could be simplified using a configuration object. Consider this improvement: const TAB_CONFIG = [
{
tab: EnvironmentDrawerTab.Overview,
icon: <IconInfoCircle className="h-4 w-4" />,
label: "Overview",
isDefault: true
},
{
tab: EnvironmentDrawerTab.Targets,
icon: <IconTarget className="h-4 w-4" />,
label: "Targets"
},
{
tab: EnvironmentDrawerTab.ReleaseChannels,
icon: <IconFilter className="h-4 w-4" />,
label: "Release Channels"
}
] as const;
// In JSX:
{TAB_CONFIG.map(({ tab, icon, label, isDefault }) => (
<TabButton
key={tab}
active={currentTab === tab || (isDefault && currentTab == null)}
onClick={() => setTab(tab)}
icon={icon}
label={label}
/>
))}
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. eh imo this isn't really needed, its only 3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @adityachoudhari26, understood. We'll proceed without the suggested refactor. ✏️ Learnings added
|
||
| /> | ||
| </div> | ||
|
|
||
| {environment != null && ( | ||
| <div className="w-full overflow-auto"> | ||
| {activeTab === "overview" && ( | ||
| {(tab === EnvironmentDrawerTab.Overview || tab == null) && ( | ||
| <Overview environment={environment} /> | ||
| )} | ||
| {activeTab === "targets" && workspace != null && ( | ||
| {tab === EnvironmentDrawerTab.Targets && workspace != null && ( | ||
| <EditFilterForm | ||
| environment={environment} | ||
| workspaceId={workspace.id} | ||
| /> | ||
| )} | ||
| {activeTab === "release-channels" && deployments != null && ( | ||
| <ReleaseChannels | ||
| environment={environment} | ||
| deployments={deployments} | ||
| /> | ||
| )} | ||
| {tab === EnvironmentDrawerTab.ReleaseChannels && | ||
| deployments != null && ( | ||
| <ReleaseChannels | ||
| environment={environment} | ||
| deployments={deployments} | ||
| /> | ||
| )} | ||
adityachoudhari26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </div> | ||
| )} | ||
| </div> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding validation for tab parameter values.
The hook handles tab state well, but it might benefit from validating that the tab value from URL params matches the
EnvironmentDrawerTabenum values.Consider this improvement:
const useEnvironmentDrawerTab = () => { const router = useRouter(); const params = useSearchParams(); const tab = params.get(tabParam); + const isValidTab = (value: string | null): value is EnvironmentDrawerTab => { + return value != null && Object.values(EnvironmentDrawerTab).includes(value as EnvironmentDrawerTab); + }; + const validTab = isValidTab(tab) ? tab : null; const setTab = (tab: EnvironmentDrawerTab | null) => { // ... existing code ... }; - return { tab, setTab }; + return { tab: validTab, setTab }; };📝 Committable suggestion