Jelajahi Sumber

Implemented owner filter for pods and hpa on expanded chart level

jnfrati 4 tahun lalu
induk
melakukan
b82f41b20c

+ 20 - 3
dashboard/src/components/events/useEvents.tsx

@@ -4,7 +4,11 @@ import api from "shared/api";
 import { Context } from "shared/Context";
 import { KubeEvent } from "shared/types";
 
-export const useKubeEvents = (resourceType: "NODE" | "POD" | "HPA") => {
+export const useKubeEvents = (
+  resourceType: "NODE" | "POD" | "HPA",
+  ownerName?: string,
+  ownerType?: string
+) => {
   const { currentCluster, currentProject } = useContext(Context);
   const [hasPorterAgent, setHasPorterAgent] = useState(false);
 
@@ -46,7 +50,14 @@ export const useKubeEvents = (resourceType: "NODE" | "POD" | "HPA") => {
     return () => {
       isSubscribed = false;
     };
-  }, [currentProject?.id, currentCluster?.id, hasPorterAgent, resourceType]);
+  }, [
+    currentProject?.id,
+    currentCluster?.id,
+    hasPorterAgent,
+    resourceType,
+    ownerType,
+    ownerName,
+  ]);
 
   const fetchData = async (clear?: boolean) => {
     const project_id = currentProject?.id;
@@ -59,11 +70,17 @@ export const useKubeEvents = (resourceType: "NODE" | "POD" | "HPA") => {
     }
 
     const type = resourceType;
+
     try {
       const data = await api
         .getKubeEvents(
           "<token>",
-          { skip: skipBy, resource_type: type },
+          {
+            skip: skipBy,
+            resource_type: type,
+            owner_name: ownerName,
+            owner_type: ownerType,
+          },
           { project_id, cluster_id }
         )
         .then((res) => res.data);

+ 0 - 12
dashboard/src/main/home/cluster-dashboard/dashboard/events/EventsTab.tsx

@@ -59,15 +59,6 @@ const EventsTab = () => {
           options={availableResourceTypes}
           onSelect={(o) => setResourceType({ ...o, value: o.value as string })}
         />
-        {/* <RightFilters> */}
-        {/* <Dropdown
-            selectedOption={currentLimit}
-            options={availableLimitOptions}
-            onSelect={(o) =>
-              setCurrentLimit({ ...o, value: o.value as number })
-            }
-          />
-        </RightFilters> */}
       </ControlRow>
       <EventsGrid>
         <InfiniteScroll
@@ -80,9 +71,6 @@ const EventsTab = () => {
             <h4>No events were found for the resource type you specified</h4>
           }
         >
-          {/* {kubeEvents.map((_, index) => (
-          <div key={index}>div - #{index}</div>
-        ))} */}
           {kubeEvents.map((event, i) => {
             return (
               <React.Fragment key={i}>

+ 1 - 1
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedChart.tsx

@@ -351,7 +351,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
       case "metrics":
         return <MetricsSection currentChart={chart} />;
       case "events":
-        return <EventsTab currentChart={chart} />;
+        return <EventsTab controllers={controllers} />;
       case "status":
         if (isLoadingChartData) {
           return (

+ 0 - 120
dashboard/src/main/home/cluster-dashboard/expanded-chart/events/EventCard.tsx

@@ -1,120 +0,0 @@
-import React, { useState } from "react";
-import styled from "styled-components";
-import { Event } from "./EventsTab";
-import Loading from "../../../../../components/Loading";
-
-type CardProps = {
-  event: Event;
-  selectEvent?: () => void;
-  overrideName?: string;
-};
-
-export const getReadableDate = (s: number) => {
-  let ts = new Date(s * 1000);
-  let date = ts.toLocaleDateString();
-  let time = ts.toLocaleTimeString([], {
-    hour: "numeric",
-    minute: "2-digit",
-  });
-  return `${time} ${date}`;
-};
-
-// Rename to Event Card
-const EventCard: React.FunctionComponent<CardProps> = ({
-  event,
-  selectEvent,
-  overrideName,
-}) => {
-  return (
-    <StyledCard onClick={() => selectEvent && selectEvent()}>
-      {event.status == 1 && (
-        <Icon status="normal" className="material-icons-outlined">
-          check
-        </Icon>
-      )}
-      {event.status == 2 && (
-        <Icon className="material-icons-outlined">autorenew</Icon>
-      )}
-      {event.status == 3 && (
-        <Icon status="critical" className="material-icons-outlined">
-          error
-        </Icon>
-      )}
-
-      <InfoWrapper>
-        <EventName>
-          {overrideName ? overrideName : event.name}
-          {event.status == 1 && " successful"}
-          {event.status == 2 && " in progress"}
-          {event.status == 3 && ` failed: ${event.info}`}
-        </EventName>
-        <TimestampContainer>
-          <i className="material-icons-outlined">access_time</i>
-          {getReadableDate(event.time)}
-        </TimestampContainer>
-      </InfoWrapper>
-    </StyledCard>
-  );
-};
-
-export default EventCard;
-
-const StyledCard = styled.div`
-  display: flex;
-  align-items: center;
-  border: 1px solid #ffffff44;
-  background: #ffffff08;
-  margin-bottom: 10px;
-  border-radius: 10px;
-  padding-left: 20px;
-  overflow: hidden;
-  height: 80px;
-  cursor: pointer;
-
-  :hover {
-    background: #ffffff11;
-    border: 1px solid #ffffff66;
-  }
-`;
-
-const Icon = styled.span<{ status?: "critical" | "normal" }>`
-  font-size: 22px;
-  margin-right: 18px;
-  color: ${({ status }) =>
-    status ? (status === "critical" ? "#cc3d42" : "#38a88a") : "#efefef"};
-  animation: ${({ status }) => !status && "rotating 3s linear infinite"};
-  @keyframes rotating {
-    from {
-      transform: rotate(0deg);
-    }
-    to {
-      transform: rotate(360deg);
-    }
-  }
-`;
-
-const InfoWrapper = styled.div`
-  display: flex;
-  flex-direction: column;
-`;
-
-const EventName = styled.div`
-  font-size: 13px;
-  font-family: "Work Sans", sans-serif;
-  font-weight: 500;
-  color: #ffffff;
-`;
-
-const TimestampContainer = styled.div`
-  display: flex;
-  align-items: center;
-  color: #ffffff55;
-  font-size: 13px;
-  margin-top: 8px;
-
-  > i {
-    margin-right: 5px;
-    font-size: 18px;
-    margin-left: -1px;
-  }
-`;

+ 0 - 94
dashboard/src/main/home/cluster-dashboard/expanded-chart/events/EventDetail.tsx

@@ -1,94 +0,0 @@
-import React, { Fragment } from "react";
-import { EventContainer } from "./EventsTab";
-import TitleSection from "components/TitleSection";
-import EventCard, { getReadableDate } from "./EventCard";
-import styled from "styled-components";
-
-interface Props {
-  container: EventContainer;
-  resetSelection: () => {};
-}
-
-const EventDetail: React.FC<Props> = (props) => {
-  return (
-    <>
-      <Flex>
-        <TitleSection handleNavBack={props.resetSelection}>
-          {props.container.name}
-        </TitleSection>
-        <P>
-          <i className="material-icons-outlined">access_time</i>
-          {getReadableDate(props.container.started_at)}
-        </P>
-      </Flex>
-      <EventsGrid>
-        {props.container.events
-          .slice(0)
-          .reverse()
-          .map((event) => {
-            return (
-              <React.Fragment key={event.index}>
-                <EventCard event={event} />
-              </React.Fragment>
-            );
-          })}
-      </EventsGrid>
-    </>
-  );
-};
-
-export default EventDetail;
-
-const Flex = styled.div`
-  display: flex;
-  align-items: center;
-  margin-bottom: 10px;
-`;
-
-const P = styled.p`
-  display: flex;
-  align-items: center;
-  color: #ffffff44;
-  font-size: 13px;
-  margin-left: 20px;
-  margin-top: 0px;
-
-  > i {
-    margin-right: 5px;
-    font-size: 18px;
-    margin-left: -1px;
-  }
-`;
-
-const BackButton = styled.div`
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  cursor: pointer;
-  font-size: 13px;
-  height: 35px;
-  padding: 5px 16px;
-  padding-right: 15px;
-  border: 1px solid #ffffff55;
-  border-radius: 100px;
-  width: ${(props: { width: string }) => props.width};
-  color: white;
-  background: #ffffff11;
-
-  :hover {
-    background: #ffffff22;
-  }
-
-  > i {
-    color: white;
-    font-size: 16px;
-    margin-right: 6px;
-    margin-left: -2px;
-  }
-`;
-
-const EventsGrid = styled.div`
-  display: grid;
-  grid-row-gap: 15px;
-  grid-template-columns: 1;
-`;

+ 44 - 15
dashboard/src/main/home/cluster-dashboard/expanded-chart/events/EventsTab.tsx

@@ -1,19 +1,47 @@
-import React, { useState } from "react";
+import React, { useMemo, useState } from "react";
 import styled from "styled-components";
 import EventCard from "components/events/EventCard";
 import Loading from "components/Loading";
 import InfiniteScroll from "react-infinite-scroll-component";
 import Dropdown from "components/Dropdown";
 import { useKubeEvents } from "components/events/useEvents";
+import { ChartType } from "shared/types";
+import _, { isObject } from "lodash";
 
 const availableResourceTypes = [
   { label: "Pods", value: "pod" },
   { label: "HPA", value: "hpa" },
 ];
 
-const EventsTab = () => {
+const EventsTab: React.FC<{
+  controllers: Record<string, Record<string, any>>;
+}> = (props) => {
+  const { controllers } = props;
   const [resourceType, setResourceType] = useState(availableResourceTypes[0]);
 
+  const [selectedControllerKey, setSelectedControllerKey] = useState(null);
+
+  const controllerOptions = useMemo(() => {
+    if (typeof controllers !== "object") {
+      return [];
+    }
+
+    return Object.entries(controllers).map(([key, value]) => ({
+      label: value?.metadata?.name,
+      value: key,
+    }));
+  }, [controllers]);
+
+  const currentControllerOption = useMemo(() => {
+    return (
+      controllerOptions?.find((c) => c.value === selectedControllerKey) ||
+      controllerOptions[0]
+    );
+  }, [selectedControllerKey, controllerOptions]);
+
+  const selectedController = controllers[currentControllerOption?.value];
+
+  console.log(controllers, currentControllerOption);
   const {
     isLoading,
     hasPorterAgent,
@@ -21,9 +49,15 @@ const EventsTab = () => {
     kubeEvents,
     loadMoreEvents,
     hasMore,
-  } = useKubeEvents(resourceType.value as any);
+  } = useKubeEvents(
+    resourceType.value as any,
+    selectedController?.metadata?.name,
+    selectedController?.kind
+  );
+
+  const hasControllers = controllers && Object.keys(controllers)?.length;
 
-  if (isLoading) {
+  if (isLoading || !hasControllers) {
     return (
       <Placeholder>
         <Loading />
@@ -53,15 +87,13 @@ const EventsTab = () => {
           options={availableResourceTypes}
           onSelect={(o) => setResourceType({ ...o, value: o.value as string })}
         />
-        {/* <RightFilters> */}
-        {/* <Dropdown
-            selectedOption={currentLimit}
-            options={availableLimitOptions}
-            onSelect={(o) =>
-              setCurrentLimit({ ...o, value: o.value as number })
-            }
+        <RightFilters>
+          <Dropdown
+            selectedOption={currentControllerOption}
+            options={controllerOptions}
+            onSelect={(o) => setSelectedControllerKey(o?.value)}
           />
-        </RightFilters> */}
+        </RightFilters>
       </ControlRow>
       <EventsGrid>
         <InfiniteScroll
@@ -74,9 +106,6 @@ const EventsTab = () => {
             <h4>No events were found for the resource type you specified</h4>
           }
         >
-          {/* {kubeEvents.map((_, index) => (
-          <div key={index}>div - #{index}</div>
-        ))} */}
           {kubeEvents.map((event, i) => {
             return (
               <React.Fragment key={i}>

+ 6 - 1
dashboard/src/shared/api.tsx

@@ -1151,7 +1151,12 @@ const installPorterAgent = baseApi<
 );
 
 const getKubeEvents = baseApi<
-  { skip: number; resource_type: string },
+  {
+    skip: number;
+    resource_type: string;
+    owner_type?: string;
+    owner_name?: string;
+  },
   { project_id: number; cluster_id: number }
 >("GET", ({ project_id, cluster_id }) => {
   return `/api/projects/${project_id}/clusters/${cluster_id}/kube_events`;