mirror of
https://github.com/komodorio/helm-dashboard.git
synced 2026-03-26 14:28:04 +00:00
Rename frontend directory (#472)
* Rename directory * Cleanup * Recover lost images * remove lint
This commit is contained in:
9
frontend/src/pages/DocsPage.tsx
Normal file
9
frontend/src/pages/DocsPage.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import SwaggerUI from "swagger-ui-react";
|
||||
import "swagger-ui-react/swagger-ui.css";
|
||||
import openapi from "../../public/openapi.json";
|
||||
|
||||
const DocsPage = () => {
|
||||
return <SwaggerUI spec={openapi} />;
|
||||
};
|
||||
|
||||
export default DocsPage;
|
||||
101
frontend/src/pages/Installed.tsx
Normal file
101
frontend/src/pages/Installed.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import InstalledPackagesHeader from "../components/InstalledPackages/InstalledPackagesHeader";
|
||||
import InstalledPackagesList from "../components/InstalledPackages/InstalledPackagesList";
|
||||
import ClustersList from "../components/ClustersList";
|
||||
import { useGetInstalledReleases } from "../API/releases";
|
||||
import { useMemo, useState } from "react";
|
||||
import Spinner from "../components/Spinner";
|
||||
import useAlertError from "../hooks/useAlertError";
|
||||
import { useParams, useNavigate } from "react-router-dom";
|
||||
import useCustomSearchParams from "../hooks/useCustomSearchParams";
|
||||
import { Release } from "../data/types";
|
||||
|
||||
function Installed() {
|
||||
const { searchParamsObject } = useCustomSearchParams();
|
||||
const { context } = useParams();
|
||||
const { filteredNamespace } = searchParamsObject;
|
||||
const selectedNamespaces = useMemo(
|
||||
() => filteredNamespace?.split("+"),
|
||||
[filteredNamespace]
|
||||
);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleClusterChange = (clusterName: string) => {
|
||||
navigate({
|
||||
pathname: `/${clusterName}/installed`,
|
||||
});
|
||||
};
|
||||
|
||||
const [filterKey, setFilterKey] = useState<string>("");
|
||||
const alertError = useAlertError();
|
||||
const { data, isLoading, isRefetching } = useGetInstalledReleases(
|
||||
context ?? "",
|
||||
{
|
||||
retry: false,
|
||||
onError: (e) => {
|
||||
alertError.setShowErrorModal({
|
||||
title: "Failed to get list of charts",
|
||||
msg: (e as Error).message,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const filteredReleases = useMemo(() => {
|
||||
return (
|
||||
data?.filter((installedPackage: Release) => {
|
||||
if (filterKey) {
|
||||
const {
|
||||
namespace: releaseNamespace,
|
||||
name: releaseName,
|
||||
chartName,
|
||||
} = installedPackage;
|
||||
|
||||
const shownByNS =
|
||||
!selectedNamespaces ||
|
||||
!selectedNamespaces.length ||
|
||||
selectedNamespaces.includes(releaseNamespace);
|
||||
const shownByStr =
|
||||
releaseName.includes(filterKey) || chartName.includes(filterKey);
|
||||
if (shownByNS && shownByStr) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return selectedNamespaces
|
||||
? selectedNamespaces.includes(installedPackage.namespace)
|
||||
: true;
|
||||
}
|
||||
}) ?? []
|
||||
);
|
||||
}, [data, filterKey, selectedNamespaces]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-row w-full">
|
||||
<ClustersList
|
||||
selectedCluster={context ?? ""}
|
||||
filteredNamespaces={selectedNamespaces}
|
||||
onClusterChange={handleClusterChange}
|
||||
installedReleases={data}
|
||||
/>
|
||||
|
||||
<div className="p-5 w-[calc(100%-17rem)]">
|
||||
<InstalledPackagesHeader
|
||||
isLoading={isLoading || isRefetching}
|
||||
filteredReleases={filteredReleases}
|
||||
setFilterKey={setFilterKey}
|
||||
/>
|
||||
|
||||
{isLoading || isRefetching ? (
|
||||
<div className="py-2">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<InstalledPackagesList filteredReleases={filteredReleases} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Installed;
|
||||
14
frontend/src/pages/NotFound.tsx
Normal file
14
frontend/src/pages/NotFound.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
function NotFound() {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
404 page not found
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default NotFound;
|
||||
67
frontend/src/pages/Repository.tsx
Normal file
67
frontend/src/pages/Repository.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { useMemo, useEffect } from "react";
|
||||
|
||||
import RepositoriesList from "../components/repository/RepositoriesList";
|
||||
import RepositoryViewer from "../components/repository/RepositoryViewer";
|
||||
import { Repository } from "../data/types";
|
||||
import { useGetRepositories } from "../API/repositories";
|
||||
import { HelmRepositories } from "../API/interfaces";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useAppContext } from "../context/AppContext";
|
||||
import useNavigateWithSearchParams from "../hooks/useNavigateWithSearchParams";
|
||||
|
||||
function RepositoryPage() {
|
||||
const { selectedRepo: repoFromParams, context } = useParams();
|
||||
const navigate = useNavigateWithSearchParams();
|
||||
const { setSelectedRepo, selectedRepo } = useAppContext();
|
||||
|
||||
const handleRepositoryChanged = (selectedRepository: Repository) => {
|
||||
navigate(`/${context}/repository/${selectedRepository.name}`, {
|
||||
replace: true,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (repoFromParams) {
|
||||
setSelectedRepo(repoFromParams);
|
||||
}
|
||||
}, [setSelectedRepo, repoFromParams]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedRepo && !repoFromParams) {
|
||||
navigate(`/${context}/repository/${selectedRepo}`, {
|
||||
replace: true,
|
||||
});
|
||||
}
|
||||
}, [selectedRepo, repoFromParams, context, navigate]);
|
||||
|
||||
const { data: repositories = [] } = useGetRepositories({
|
||||
onSuccess: (data: HelmRepositories) => {
|
||||
const sortedData = data?.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
if (sortedData && sortedData.length > 0 && !repoFromParams) {
|
||||
handleRepositoryChanged(sortedData[0]);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const selectedRepository = useMemo(() => {
|
||||
if (repoFromParams) {
|
||||
return repositories?.find((repo) => repo.name === repoFromParams);
|
||||
}
|
||||
}, [repositories, repoFromParams]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-row p-5 gap-4">
|
||||
<RepositoriesList
|
||||
repositories={repositories}
|
||||
onRepositoryChanged={handleRepositoryChanged}
|
||||
selectedRepository={selectedRepository}
|
||||
/>
|
||||
<div className="w-[calc(100%-21rem)]">
|
||||
<RepositoryViewer repository={selectedRepository} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default RepositoryPage;
|
||||
101
frontend/src/pages/Revision.tsx
Normal file
101
frontend/src/pages/Revision.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useMemo } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import RevisionDetails from "../components/revision/RevisionDetails";
|
||||
import RevisionsList from "../components/revision/RevisionsList";
|
||||
import { ReleaseRevision } from "../data/types";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import apiService from "../API/apiService";
|
||||
import Spinner from "../components/Spinner";
|
||||
|
||||
const descendingSort = (r1: ReleaseRevision, r2: ReleaseRevision) =>
|
||||
r1.revision - r2.revision < 0 ? 1 : -1;
|
||||
|
||||
function Revision() {
|
||||
const { revision = "", ...restParams } = useParams();
|
||||
|
||||
const selectedRevision = revision ? parseInt(revision, 10) : 0;
|
||||
|
||||
const { data: releaseRevisions, isLoading: isLoadingHistory } = useQuery<
|
||||
ReleaseRevision[]
|
||||
>({
|
||||
//eslint-ignore
|
||||
//@ts-ignore
|
||||
queryKey: ["releasesHistory", restParams],
|
||||
queryFn: apiService.getReleasesHistory,
|
||||
});
|
||||
|
||||
const latestRevision = useMemo(
|
||||
() =>
|
||||
Array.isArray(releaseRevisions) &&
|
||||
releaseRevisions.reduce((max, revisionData) => {
|
||||
return Math.max(max, revisionData.revision);
|
||||
}, Number.MIN_SAFE_INTEGER),
|
||||
[releaseRevisions]
|
||||
);
|
||||
|
||||
const sortedReleases = useMemo(
|
||||
() => (releaseRevisions as ReleaseRevision[])?.sort(descendingSort),
|
||||
[releaseRevisions]
|
||||
);
|
||||
|
||||
const selectedRelease = useMemo(() => {
|
||||
if (selectedRevision && releaseRevisions) {
|
||||
return (releaseRevisions as ReleaseRevision[]).find(
|
||||
(r: ReleaseRevision) => r.revision === selectedRevision
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}, [releaseRevisions, selectedRevision]);
|
||||
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="flex flex-col gap-2 w-1/6 min-h-screen bg-[#E8EDF2] pb-4">
|
||||
<label className="mt-5 mx-5 text-sm text-dark font-semibold">
|
||||
Revisions
|
||||
</label>
|
||||
{isLoadingHistory ? (
|
||||
<RevisionSidebarSkeleton />
|
||||
) : (
|
||||
<RevisionsList
|
||||
releaseRevisions={sortedReleases}
|
||||
selectedRevision={selectedRevision}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-5/6 min-h-screen bg-body-background pb-4">
|
||||
{isLoadingHistory ? (
|
||||
<div className=" p-4">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : selectedRelease ? (
|
||||
<RevisionDetails
|
||||
//@ts-ignore
|
||||
release={selectedRelease}
|
||||
installedRevision={
|
||||
//@ts-ignore
|
||||
releaseRevisions?.[0] as ReleaseRevision
|
||||
}
|
||||
isLatest={selectedRelease.revision === latestRevision}
|
||||
latestRevision={latestRevision.revision}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const RevisionSidebarSkeleton = () => {
|
||||
return (
|
||||
<>
|
||||
<div className="border rounded-md mx-5 p-2 gap-4 animate-pulse h-[74px] w-[88%] bg-gray-100" />
|
||||
<div className="border rounded-md mx-5 p-2 gap-4 animate-pulse h-[74px] w-[88%] bg-gray-100" />
|
||||
<div className="border rounded-md mx-5 p-2 gap-4 animate-pulse h-[74px] w-[88%] bg-gray-100" />
|
||||
<div className="border rounded-md mx-5 p-2 gap-4 animate-pulse h-[74px] w-[88%] bg-gray-100" />
|
||||
<div className="border rounded-md mx-5 p-2 gap-4 animate-pulse h-[74px] w-[88%] bg-gray-100" />
|
||||
<div className="border rounded-md mx-5 p-2 gap-4 animate-pulse h-[74px] w-[88%] bg-gray-100" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Revision;
|
||||
Reference in New Issue
Block a user