forked from github-starred/komodo
more type safe tabs
This commit is contained in:
@@ -10,8 +10,10 @@ import { ResourceComponents } from "..";
|
||||
import { DeploymentTable } from "../deployment/table";
|
||||
import { BuildConfig } from "./config";
|
||||
|
||||
type BuildTabsView = "Config" | "Info" | "Deployments";
|
||||
|
||||
export const BuildTabs = ({ id }: { id: string }) => {
|
||||
const [view, setView] = useLocalStorage<"Config" | "Info" | "Deployments">(
|
||||
const [view, setView] = useLocalStorage<BuildTabsView>(
|
||||
"build-tabs-v1",
|
||||
"Config"
|
||||
);
|
||||
@@ -20,7 +22,7 @@ export const BuildTabs = ({ id }: { id: string }) => {
|
||||
);
|
||||
const deploymentsDisabled = (deployments?.length || 0) === 0;
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<BuildTabsView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Config",
|
||||
@@ -46,6 +48,8 @@ export const BuildTabs = ({ id }: { id: string }) => {
|
||||
);
|
||||
|
||||
switch (view) {
|
||||
case "Config":
|
||||
return <BuildConfig id={id} titleOther={Selector} />;
|
||||
case "Info":
|
||||
return <BuildInfo id={id} titleOther={Selector} />;
|
||||
case "Deployments":
|
||||
@@ -57,7 +61,5 @@ export const BuildTabs = ({ id }: { id: string }) => {
|
||||
<DeploymentTable deployments={deployments ?? []} />
|
||||
</Section>
|
||||
);
|
||||
default:
|
||||
return <BuildConfig id={id} titleOther={Selector} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,14 +18,17 @@ export const DeploymentTabs = ({ id }: { id: string }) => {
|
||||
return <DeploymentTabsInner deployment={deployment} />;
|
||||
};
|
||||
|
||||
type DeploymentTabsView = "Config" | "Log" | "Inspect" | "Terminal";
|
||||
|
||||
const DeploymentTabsInner = ({
|
||||
deployment,
|
||||
}: {
|
||||
deployment: Types.DeploymentListItem;
|
||||
}) => {
|
||||
const [_view, setView] = useLocalStorage<
|
||||
"Config" | "Log" | "Inspect" | "Terminal"
|
||||
>("deployment-tabs-v1", "Config");
|
||||
const [_view, setView] = useLocalStorage<DeploymentTabsView>(
|
||||
"deployment-tabs-v1",
|
||||
"Config"
|
||||
);
|
||||
const { specificLogs, specificInspect, specificTerminal } = usePermissions({
|
||||
type: "Deployment",
|
||||
id: deployment.id,
|
||||
@@ -55,7 +58,7 @@ const DeploymentTabsInner = ({
|
||||
? "Config"
|
||||
: _view;
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<DeploymentTabsView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Config",
|
||||
@@ -109,13 +112,13 @@ const DeploymentTabsInner = ({
|
||||
);
|
||||
|
||||
switch (view) {
|
||||
case "Config":
|
||||
return <DeploymentConfig id={deployment.id} titleOther={Selector} />;
|
||||
case "Log":
|
||||
return <DeploymentLogs id={deployment.id} titleOther={Selector} />;
|
||||
case "Inspect":
|
||||
return <DeploymentInspect id={deployment.id} titleOther={Selector} />;
|
||||
case "Terminal":
|
||||
return <ContainerTerminal query={terminalQuery} titleOther={Selector} />;
|
||||
default:
|
||||
return <DeploymentConfig id={deployment.id} titleOther={Selector} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ export const ServerInfo = ({
|
||||
);
|
||||
}
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<ServerInfoView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Containers",
|
||||
|
||||
@@ -48,7 +48,7 @@ export const ServerTabs = ({ id }: { id: string }) => {
|
||||
|
||||
const noResources = noDeployments && noRepos && noStacks;
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<ServerTabView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Config",
|
||||
@@ -88,6 +88,8 @@ export const ServerTabs = ({ id }: { id: string }) => {
|
||||
);
|
||||
|
||||
switch (view) {
|
||||
case "Config":
|
||||
return <ServerConfig id={id} titleOther={Selector} />;
|
||||
case "Stats":
|
||||
return <ServerStats id={id} titleOther={Selector} />;
|
||||
case "Docker":
|
||||
@@ -96,8 +98,6 @@ export const ServerTabs = ({ id }: { id: string }) => {
|
||||
return <ServerTabsResources id={id} Selector={Selector} />;
|
||||
case "Terminals":
|
||||
return <ServerTabsTerminals id={id} Selector={Selector} />;
|
||||
default:
|
||||
return <ServerConfig id={id} titleOther={Selector} />;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,10 +11,13 @@ import { StackServices } from "./services";
|
||||
import { StackLogs } from "./log";
|
||||
import { StackConfig } from "./config";
|
||||
|
||||
type StackTabsView = "Config" | "Info" | "Services" | "Log";
|
||||
|
||||
export const StackTabs = ({ id }: { id: string }) => {
|
||||
const [_view, setView] = useLocalStorage<
|
||||
"Config" | "Info" | "Services" | "Log"
|
||||
>("stack-tabs-v1", "Config");
|
||||
const [_view, setView] = useLocalStorage<StackTabsView>(
|
||||
"stack-tabs-v1",
|
||||
"Config"
|
||||
);
|
||||
const info = useStack(id)?.info;
|
||||
const { specific, specificLogs } = usePermissions({ type: "Stack", id });
|
||||
|
||||
@@ -34,7 +37,7 @@ export const StackTabs = ({ id }: { id: string }) => {
|
||||
? "Config"
|
||||
: _view;
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<StackTabsView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Config",
|
||||
@@ -44,7 +47,7 @@ export const StackTabs = ({ id }: { id: string }) => {
|
||||
hidden: hideInfo,
|
||||
},
|
||||
{
|
||||
value: "Service",
|
||||
value: "Services",
|
||||
disabled: hideServices,
|
||||
},
|
||||
{
|
||||
@@ -66,13 +69,13 @@ export const StackTabs = ({ id }: { id: string }) => {
|
||||
);
|
||||
|
||||
switch (view) {
|
||||
case "Config":
|
||||
return <StackConfig id={id} titleOther={Selector} />;
|
||||
case "Info":
|
||||
return <StackInfo id={id} titleOther={Selector} />;
|
||||
case "Services":
|
||||
return <StackServices id={id} titleOther={Selector} />;
|
||||
case "Log":
|
||||
return <StackLogs id={id} titleOther={Selector} />;
|
||||
default:
|
||||
return <StackConfig id={id} titleOther={Selector} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ import { ResourceSyncConfig } from "./config";
|
||||
|
||||
type ResourceSyncTabsView = "Config" | "Info" | "Execute" | "Commit";
|
||||
const syncTabsViewAtom = atomWithStorage<ResourceSyncTabsView>(
|
||||
"sync-tabs-v4",
|
||||
"sync-tabs-v5",
|
||||
"Config"
|
||||
);
|
||||
|
||||
@@ -58,7 +58,7 @@ export const SyncTabs = ({ id }: { id: string }) => {
|
||||
const { view, setView, hideInfo, showPending } =
|
||||
useResourceSyncTabsView(sync);
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<ResourceSyncTabsView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Config",
|
||||
@@ -90,13 +90,13 @@ export const SyncTabs = ({ id }: { id: string }) => {
|
||||
);
|
||||
|
||||
switch (view) {
|
||||
case "Config":
|
||||
return <ResourceSyncConfig id={id} titleOther={Selector} />;
|
||||
case "Info":
|
||||
return <ResourceSyncInfo id={id} titleOther={Selector} />;
|
||||
case "Execute":
|
||||
return <ResourceSyncPending id={id} titleOther={Selector} />;
|
||||
case "Commit":
|
||||
return <ResourceSyncPending id={id} titleOther={Selector} />;
|
||||
default:
|
||||
return <ResourceSyncConfig id={id} titleOther={Selector} />;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -249,7 +249,7 @@ const ContainerTabs = ({
|
||||
? "Log"
|
||||
: _view;
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<ContainerTabsView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Log",
|
||||
|
||||
@@ -261,7 +261,7 @@ const StackServiceTabs = ({
|
||||
? "Log"
|
||||
: _view;
|
||||
|
||||
const tabsNoContent = useMemo<TabNoContent[]>(
|
||||
const tabsNoContent = useMemo<TabNoContent<StackServiceTabsView>[]>(
|
||||
() => [
|
||||
{
|
||||
value: "Log",
|
||||
|
||||
@@ -9,21 +9,24 @@ import {
|
||||
} from "./select";
|
||||
import { cn } from "@lib/utils";
|
||||
|
||||
export type Tab = {
|
||||
export type Tab<Value extends string = string> = {
|
||||
label?: string;
|
||||
hidden?: boolean;
|
||||
disabled?: boolean;
|
||||
value: string;
|
||||
value: Value;
|
||||
content: ReactNode;
|
||||
};
|
||||
|
||||
export type TabNoContent = Omit<Tab, "content">;
|
||||
export type TabNoContent<Value extends string = string> = Omit<
|
||||
Tab<Value>,
|
||||
"content"
|
||||
>;
|
||||
|
||||
export const MobileFriendlyTabs = (props: {
|
||||
tabs: Tab[];
|
||||
export const MobileFriendlyTabs = <Value extends string = string>(props: {
|
||||
tabs: Tab<Value>[];
|
||||
actions?: ReactNode;
|
||||
value: string;
|
||||
onValueChange: (value: string) => void;
|
||||
value: Value;
|
||||
onValueChange: (value: Value) => void;
|
||||
}) => {
|
||||
return (
|
||||
<MobileFriendlyTabsWrapper
|
||||
@@ -34,15 +37,15 @@ export const MobileFriendlyTabs = (props: {
|
||||
);
|
||||
};
|
||||
|
||||
export const MobileFriendlyTabsWrapper = ({
|
||||
export const MobileFriendlyTabsWrapper = <Value extends string = string>({
|
||||
Selector,
|
||||
tabs,
|
||||
value,
|
||||
className,
|
||||
}: {
|
||||
Selector: ReactNode;
|
||||
tabs: Tab[];
|
||||
value: string;
|
||||
tabs: Tab<Value>[];
|
||||
value: Value;
|
||||
className?: string;
|
||||
}) => {
|
||||
return (
|
||||
@@ -53,24 +56,24 @@ export const MobileFriendlyTabsWrapper = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const MobileFriendlyTabsSelector = ({
|
||||
export const MobileFriendlyTabsSelector = <Value extends string = string>({
|
||||
tabs: _tabs,
|
||||
actions,
|
||||
value,
|
||||
onValueChange,
|
||||
tabsTriggerClassname,
|
||||
}: {
|
||||
tabs: TabNoContent[];
|
||||
tabs: TabNoContent<Value>[];
|
||||
actions?: ReactNode;
|
||||
value: string;
|
||||
onValueChange: (value: string) => void;
|
||||
value: Value;
|
||||
onValueChange: (value: Value) => void;
|
||||
tabsTriggerClassname?: string;
|
||||
}) => {
|
||||
const tabs = _tabs.filter((t) => !t.hidden);
|
||||
return (
|
||||
<>
|
||||
<div className="hidden md:flex items-center justify-between">
|
||||
<Tabs value={value} onValueChange={onValueChange}>
|
||||
<Tabs value={value} onValueChange={onValueChange as any}>
|
||||
<TabsList className="justify-start w-fit">
|
||||
{tabs.map((tab) => (
|
||||
<TabsTrigger
|
||||
@@ -107,12 +110,12 @@ export const MobileFriendlyTabsSelector = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const MobileFriendlyTabsContent = ({
|
||||
export const MobileFriendlyTabsContent = <Value extends string = string>({
|
||||
tabs,
|
||||
value,
|
||||
}: {
|
||||
tabs: Tab[];
|
||||
value: string;
|
||||
value: Value;
|
||||
}) => {
|
||||
return tabs.find((tab) => tab.value === value)?.content;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user