feature/freelens-parity-complete #87

Merged
sarman merged 16 commits from feature/freelens-parity-complete into master 2026-06-10 01:06:11 +00:00
2 changed files with 74 additions and 25 deletions
Showing only changes of commit a9cc0e12cc - Show all commits

View File

@ -52,7 +52,7 @@ pub async fn get_pod_metrics(
} }
let json_output = &output.stdout; let json_output = &output.stdout;
crate::metrics::client::parse_pod_metrics(&json_output) crate::metrics::client::parse_pod_metrics(json_output)
.map_err(|e| format!("Failed to parse pod metrics: {e}")) .map_err(|e| format!("Failed to parse pod metrics: {e}"))
} }
@ -103,6 +103,6 @@ pub async fn get_node_metrics(
} }
let json_output = &output.stdout; let json_output = &output.stdout;
crate::metrics::client::parse_node_metrics(&json_output) crate::metrics::client::parse_node_metrics(json_output)
.map_err(|e| format!("Failed to parse node metrics: {e}")) .map_err(|e| format!("Failed to parse node metrics: {e}"))
} }

View File

@ -1,6 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Button } from "@/components/ui";
import { PauseCircle, PlayCircle, Play, Pencil, Trash2, FileText } from "lucide-react"; import { PauseCircle, PlayCircle, Play, Pencil, Trash2, FileText, Settings } from "lucide-react";
import type { CronJobInfo } from "@/lib/tauriCommands"; import type { CronJobInfo } from "@/lib/tauriCommands";
import { import {
suspendCronjobCmd, suspendCronjobCmd,
@ -13,6 +13,9 @@ import { ResourceActionMenu } from "./ResourceActionMenu";
import { ConfirmDeleteDialog } from "./ConfirmDeleteDialog"; import { ConfirmDeleteDialog } from "./ConfirmDeleteDialog";
import { EditResourceModal } from "./EditResourceModal"; import { EditResourceModal } from "./EditResourceModal";
import { WorkloadLogsModal } from "./WorkloadLogsModal"; import { WorkloadLogsModal } from "./WorkloadLogsModal";
import { useColumnConfig } from "@/hooks/useColumnConfig";
import { DEFAULT_COLUMNS } from "@/config/defaultColumns";
import { ColumnConfigModal } from "@/components/tables/ColumnConfigModal";
interface CronJobListProps { interface CronJobListProps {
cronJobs: CronJobInfo[]; cronJobs: CronJobInfo[];
@ -39,6 +42,11 @@ export function CronJobList({
const [activeModal, setActiveModal] = useState<ActiveModal>(null); const [activeModal, setActiveModal] = useState<ActiveModal>(null);
const [isDeleting, setIsDeleting] = useState(false); const [isDeleting, setIsDeleting] = useState(false);
const [actionError, setActionError] = useState<string | null>(null); const [actionError, setActionError] = useState<string | null>(null);
const [showColumnConfig, setShowColumnConfig] = useState(false);
// Configurable columns
const columnConfig = useColumnConfig("cronjobs", DEFAULT_COLUMNS.cronjobs);
const { isColumnVisible } = columnConfig;
const openEdit = async (cj: CronJobInfo) => { const openEdit = async (cj: CronJobInfo) => {
setActionError(null); setActionError(null);
@ -102,18 +110,32 @@ export function CronJobList({
{actionError && ( {actionError && (
<p className="mb-2 text-sm text-destructive">{actionError}</p> <p className="mb-2 text-sm text-destructive">{actionError}</p>
)} )}
<div className="flex items-center justify-between mb-2">
<div className="text-sm text-muted-foreground">
{cronJobs.length} {cronJobs.length === 1 ? "cron job" : "cron jobs"}
</div>
<Button
variant="outline"
size="sm"
onClick={() => setShowColumnConfig(true)}
className="flex items-center gap-1"
>
<Settings className="h-3.5 w-3.5" />
Columns
</Button>
</div>
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<Table> <Table>
<TableHeader> <TableHeader>
<TableRow> <TableRow>
<TableHead>Name</TableHead> {isColumnVisible("name") && <TableHead>Name</TableHead>}
<TableHead>Namespace</TableHead> {isColumnVisible("namespace") && <TableHead>Namespace</TableHead>}
<TableHead>Schedule</TableHead> {isColumnVisible("schedule") && <TableHead>Schedule</TableHead>}
<TableHead>Active</TableHead> {isColumnVisible("active") && <TableHead>Active</TableHead>}
<TableHead>Last Schedule</TableHead> {isColumnVisible("lastSchedule") && <TableHead>Last Schedule</TableHead>}
<TableHead>Age</TableHead> {isColumnVisible("age") && <TableHead>Age</TableHead>}
<TableHead>Labels</TableHead> {isColumnVisible("labels") && <TableHead>Labels</TableHead>}
<TableHead className="text-right">Actions</TableHead> {isColumnVisible("actions") && <TableHead className="text-right">Actions</TableHead>}
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
@ -126,18 +148,27 @@ export function CronJobList({
) : ( ) : (
cronJobs.map((cj) => ( cronJobs.map((cj) => (
<TableRow key={`${cj.name}-${cj.namespace}`}> <TableRow key={`${cj.name}-${cj.namespace}`}>
<TableCell className="font-medium">{cj.name}</TableCell> {isColumnVisible("name") && (
<TableCell>{cj.namespace}</TableCell> <TableCell className="font-medium">{cj.name}</TableCell>
<TableCell>{cj.schedule}</TableCell> )}
<TableCell>{cj.active}</TableCell> {isColumnVisible("namespace") && (
<TableCell>{cj.last_schedule}</TableCell> <TableCell className="text-muted-foreground">{cj.namespace}</TableCell>
<TableCell className="text-muted-foreground">{cj.age}</TableCell> )}
<TableCell> {isColumnVisible("schedule") && <TableCell>{cj.schedule}</TableCell>}
{Object.entries(cj.labels) {isColumnVisible("active") && <TableCell>{cj.active}</TableCell>}
.map(([k, v]) => `${k}=${v}`) {isColumnVisible("lastSchedule") && <TableCell>{cj.last_schedule}</TableCell>}
.join(", ")} {isColumnVisible("age") && (
</TableCell> <TableCell className="text-muted-foreground">{cj.age}</TableCell>
<TableCell className="text-right"> )}
{isColumnVisible("labels") && (
<TableCell>
{Object.entries(cj.labels)
.map(([k, v]) => `${k}=${v}`)
.join(", ")}
</TableCell>
)}
{isColumnVisible("actions") && (
<TableCell className="text-right">
<ResourceActionMenu <ResourceActionMenu
actions={[ actions={[
{ {
@ -175,7 +206,8 @@ export function CronJobList({
}, },
]} ]}
/> />
</TableCell> </TableCell>
)}
</TableRow> </TableRow>
)) ))
)} )}
@ -217,6 +249,23 @@ export function CronJobList({
onConfirm={handleDelete} onConfirm={handleDelete}
/> />
)} )}
<ColumnConfigModal
open={showColumnConfig}
onOpenChange={setShowColumnConfig}
resourceType="CronJobs"
columnConfig={columnConfig}
columnLabels={{
name: "Name",
namespace: "Namespace",
schedule: "Schedule",
active: "Active",
lastSchedule: "Last Schedule",
age: "Age",
labels: "Labels",
actions: "Actions",
}}
/>
</> </>
); );
} }