Skip to content

Commit

Permalink
Better Clusters/Contracts List (#76)
Browse files Browse the repository at this point in the history
* refactor: Enhance ContractDisplay with improved interval rendering and UI components

* feat: Add mock contracts for testing contract display states

* update schema to include contracts on clusters endpoint

* feat: Enhance cluster listing with contract status and mock data

* refactor: Improve layout and spacing in cluster and contract displays

* fix: Remove optional chaining for cluster contract properties

* release: v0.1.45

* fmt

* refactor: Simplify cluster contract display and remove interval details

* release: v0.1.46

* release: v0.1.47
  • Loading branch information
JohnPhamous authored Feb 19, 2025
1 parent e08e1d3 commit a22283a
Show file tree
Hide file tree
Showing 9 changed files with 946 additions and 250 deletions.
3 changes: 2 additions & 1 deletion .cursor/rules/cli.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ globs: *.(ts|tsx)
- This is a CLI program written in Deno using the `commander` library and `@commander-js/extra-typings`.

- When using node globals like `console.log`, `setTimeout`, `process`, etc, import them from the corresponding explicit `node:console`, `node:timers`, and `node:process`, etc.
- Where possible, use the `openapi-typescript`/`openapi-fetch` client instead of writing raw fetch calls.
- Where possible, use the `openapi-typescript`/`openapi-fetch` client instead of writing raw fetch calls.
- <Badge> renders the content as uppercase so tests should assert on the uppercase text.
59 changes: 57 additions & 2 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
},
"dependencies": {
"@commander-js/extra-typings": "^12.1.0",
"@inkjs/ui": "^2.0.0",
"@inquirer/prompts": "^5.1.2",
"@types/ms": "^0.7.34",
"axios": "^1.7.2",
Expand All @@ -22,8 +23,10 @@
"ink": "^5.0.1",
"ink-confirm-input": "^2.0.0",
"ink-spinner": "^5.0.0",
"ink-testing-library": "^4.0.0",
"ink-text-input": "^6.0.0",
"inquirer": "^10.1.2",
"little-date": "^1.0.0",
"ms": "^2.1.3",
"node-fetch": "^3.3.2",
"openapi-fetch": "^0.11.1",
Expand All @@ -45,5 +48,5 @@
"peerDependencies": {
"typescript": "^5.6.2"
},
"version": "0.1.44"
"version": "0.1.46"
}
101 changes: 75 additions & 26 deletions src/lib/clusters/clusters.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { Command } from "@commander-js/extra-typings";
import * as console from "node:console";
import { clearInterval, setInterval, setTimeout } from "node:timers";
import { Badge } from "@inkjs/ui";
import { Box, render, Text, useApp } from "ink";
import Spinner from "ink-spinner";
import * as console from "node:console";
import { clearInterval, setInterval, setTimeout } from "node:timers";
// biome-ignore lint/style/useImportType: <explanation>
import React, { useEffect, useState } from "react";
import yaml from "yaml";
import { apiClient } from "../../apiClient.ts";
Expand All @@ -14,6 +16,7 @@ import {
KUBECONFIG_PATH,
syncKubeconfig,
} from "./kubeconfig.ts";
import type { UserFacingCluster } from "./types.ts";

export function registerClusters(program: Command) {
const clusters = program
Expand Down Expand Up @@ -96,33 +99,79 @@ export function registerClusters(program: Command) {
function ClusterDisplay({
clusters,
}: {
clusters: Array<{
name: string;
kubernetes_api_url: string;
kubernetes_namespace: string;
}>;
clusters: Array<UserFacingCluster>;
}) {
return (
<Box flexDirection="column">
<Box flexDirection="column" gap={2}>
{clusters.map((cluster, index) => (
<Box key={`${cluster.name}-${index}`} flexDirection="column">
<Row headWidth={11} head="name" value={cluster.name} />
<Row
headWidth={11}
head="k8s api"
value={cluster.kubernetes_api_url}
/>
<Row
headWidth={11}
head="namespace"
value={cluster.kubernetes_namespace}
/>
</Box>
<ClusterRow cluster={cluster} key={`${cluster.name}-${index}`} />
))}
</Box>
);
}

const ClusterRow = ({ cluster }: { cluster: UserFacingCluster }) => {
if (cluster.contract) {
return <ClusterRowWithContracts cluster={cluster} />;
}

return (
<Box flexDirection="column">
<Row headWidth={11} head="name" value={cluster.name} />
<Row
headWidth={11}
head="k8s api"
value={cluster.kubernetes_api_url || ""}
/>
<Row
headWidth={11}
head="namespace"
value={cluster.kubernetes_namespace}
/>
</Box>
);
};

const COLUMN_WIDTH = 11;

const ClusterRowWithContracts = (
{ cluster }: {
cluster: UserFacingCluster;
},
) => {
if (!cluster.contract) {
return null;
}

return (
<Box flexDirection="column" gap={1}>
<Box>
<Badge color="cyan">{cluster.contract.id}</Badge>
</Box>

<Box flexDirection="column">
<Row headWidth={COLUMN_WIDTH} head="Name" value={cluster.name} />
<Row
headWidth={COLUMN_WIDTH}
head="K8s API"
value={cluster.kubernetes_api_url || ""}
/>
<Row
headWidth={COLUMN_WIDTH}
head="Namespace"
value={cluster.kubernetes_namespace}
/>

<Row
headWidth={COLUMN_WIDTH}
head="Add User"
value={`sf clusters users add --cluster ${cluster.name} --user myuser`}
/>
</Box>
</Box>
);
};

async function listClustersAction({
returnJson,
token,
Expand Down Expand Up @@ -156,11 +205,11 @@ async function listClustersAction({
} else {
render(
<ClusterDisplay
clusters={data.data.map((cluster) => ({
name: cluster.name,
kubernetes_api_url: cluster.kubernetes_api_url || "",
kubernetes_namespace: cluster.kubernetes_namespace || "",
}))}
clusters={data.data.filter((
cluster,
): cluster is UserFacingCluster =>
cluster.contract?.status === "active" || !cluster.contract
)}
/>,
);
}
Expand Down
Loading

0 comments on commit a22283a

Please sign in to comment.