Przeglądaj źródła

Merge branch '0.8.0-pod-events-managment' into dev

merge w events
Alexander Belanger 4 lat temu
rodzic
commit
ec32fa0e40

+ 21 - 9
dashboard/src/components/events/EventsContext.tsx

@@ -17,17 +17,22 @@ export type Event = {
   timestamp: string;
 };
 
-type EventsContextType = {
+type EventController = { type: string; name: string };
+
+export type EventsContextType = {
   isPorterAgentInstalled: boolean;
   isPorterAgentInstalling: boolean;
   isLoading: boolean;
   eventList: Event[];
   selectedEvent: Event | null;
+  availableControllers: EventController[];
+  enableNodeEvents: boolean;
   selectEvent: (id: number) => void;
   clearSelectedEvent: () => void;
   setLimit: (limit: number) => void;
   setResourceType: (newResourceType: "pod" | "hpa" | "node") => void;
   installPorterAgent: () => Promise<void>;
+  setSelectedController: (controllerName: EventController) => void;
 };
 
 const defaultEventContext: EventsContextType = {
@@ -36,19 +41,20 @@ const defaultEventContext: EventsContextType = {
   isPorterAgentInstalling: false,
   isLoading: true,
   selectedEvent: null,
+  enableNodeEvents: false,
+  availableControllers: [],
   selectEvent: () => {},
   clearSelectedEvent: () => {},
   setLimit: () => {},
   setResourceType: () => {},
   installPorterAgent: async () => {},
+  setSelectedController: async () => {},
 };
 
 export const EventContext = createContext<EventsContextType>(
   defaultEventContext
 );
 
-type EventController = { type: string; name: string };
-
 type Props = {
   controllers: EventController[];
   enableNodeEvents: boolean;
@@ -104,6 +110,10 @@ const EventsContextProvider: React.FC<Props> = ({
   }, [isPorterAgentInstalling]);
 
   useEffect(() => {
+    if (!selectedController || !isPorterAgentInstalled) {
+      return;
+    }
+
     setIsLoading(true);
     // Clear out event list if the resource type or the selected controller changed
     if (
@@ -113,8 +123,8 @@ const EventsContextProvider: React.FC<Props> = ({
       setEventList([]);
     }
 
-    getEventList();
-  }, [isPorterAgentInstalled, selectedController, resourceType, sortBy]);
+    getEventList().then(() => setIsLoading(false));
+  }, [isPorterAgentInstalled, selectedController, resourceType, sortBy, limit]);
 
   const checkIfPorterAgentIsInstalled = async () => {
     try {
@@ -130,7 +140,6 @@ const EventsContextProvider: React.FC<Props> = ({
       setIsPorterAgentInstalled(true);
     } catch (error) {
       setIsPorterAgentInstalled(false);
-      setCurrentError(JSON.stringify(error));
     }
   };
 
@@ -167,8 +176,8 @@ const EventsContextProvider: React.FC<Props> = ({
           skip: eventList.length,
           type: resourceType,
           sort_by: sortBy,
-          owner_name: selectedController.name,
-          owner_type: selectedController.type,
+          owner_name: selectedController?.name,
+          owner_type: selectedController?.type,
         },
         {
           cluster_id: currentCluster.id,
@@ -179,7 +188,7 @@ const EventsContextProvider: React.FC<Props> = ({
       setEventList(newEventList);
     } catch (error) {
       setEventList([]);
-      setCurrentError(JSON.stringify(error));
+      setCurrentError((error as Error)?.message || JSON.stringify(error));
     }
   };
 
@@ -195,16 +204,19 @@ const EventsContextProvider: React.FC<Props> = ({
   return (
     <EventContext.Provider
       value={{
+        enableNodeEvents,
         isPorterAgentInstalled,
         isPorterAgentInstalling,
         isLoading,
         eventList,
         selectedEvent,
+        availableControllers: controllers,
         selectEvent,
         clearSelectedEvent,
         setLimit,
         setResourceType,
         installPorterAgent,
+        setSelectedController,
       }}
     >
       {children}

+ 67 - 96
dashboard/src/components/events/EventsList.tsx

@@ -1,118 +1,80 @@
-import React, { useContext, useEffect, useState } from "react";
+import React, { useContext, useEffect, useMemo, useState } from "react";
 import styled from "styled-components";
 import Dropdown from "components/Dropdown";
-import { Event, EventContext } from "./EventsContext";
+import { EventContext } from "./EventsContext";
 import EventCard from "./EventCard";
 
-const mockData = [
-  {
-    id: 1,
-    project_id: 1,
-    cluster_id: 6,
-    owner_name: "pod-test",
-    owner_type: "deployment",
-    event_type: "critical",
-    resource_type: "pod",
-    name: "pod-test-1",
-    namespace: "default",
-    message: "",
-    reason: "OOM killed",
-    timestamp: "2021-06-30T21:48:23Z",
-  },
-  {
-    id: 2,
-    project_id: 1,
-    cluster_id: 6,
-    owner_name: "pod-test",
-    owner_type: "deployment",
-    event_type: "normal",
-    resource_type: "pod",
-    name: "pod-test-2",
-    namespace: "default",
-    message: "",
-    reason: "OOM killed",
-    timestamp: "2021-06-30T21:48:23Z",
-  },
-  {
-    id: 3,
-    project_id: 1,
-    cluster_id: 6,
-    owner_name: "pod-test",
-    owner_type: "deployment",
-    event_type: "critical",
-    resource_type: "pod",
-    name: "pod-test-2",
-    namespace: "default",
-    message: "",
-    reason: "OOM killed",
-    timestamp: "2021-06-30T21:48:23Z",
-  },
-  {
-    id: 4,
-    project_id: 1,
-    cluster_id: 6,
-    owner_name: "pod-test",
-    owner_type: "deployment",
-    event_type: "critical",
-    resource_type: "pod",
-    name: "pod-test-2",
-    namespace: "default",
-    message: "",
-    reason: "OOM killed",
-    timestamp: "2021-06-30T21:48:23Z",
-  },
-  {
-    id: 5,
-    project_id: 1,
-    cluster_id: 6,
-    owner_name: "pod-test",
-    owner_type: "deployment",
-    event_type: "critical",
-    resource_type: "pod",
-    name: "pod-test-2",
-    namespace: "default",
-    message: "",
-    reason: "OOM killed",
-    timestamp: "2021-06-30T21:48:23Z",
-  },
-  {
-    id: 6,
-    project_id: 1,
-    cluster_id: 6,
-    owner_name: "pod-test",
-    owner_type: "deployment",
-    event_type: "critical",
-    resource_type: "pod",
-    name: "pod-test-2",
-    namespace: "default",
-    message: "",
-    reason: "OOM killed",
-    timestamp: "2021-06-30T21:48:23Z",
-  },
-];
-
 const EventsList: React.FunctionComponent = ({}) => {
-  const { eventList, selectEvent, setResourceType } = useContext(EventContext);
+  const {
+    eventList,
+    selectEvent,
+    setResourceType,
+    setLimit,
+    availableControllers,
+    setSelectedController,
+    enableNodeEvents,
+  } = useContext(EventContext);
 
-  const handleEventTypeSelection = (option: {
+  const handleResourceTypeSelection = (option: {
     label: string;
     value: "pod" | "hpa";
   }) => {
     setResourceType(option.value);
   };
 
+  const handleSetLimit = (option: { label: string; value: number }) => {
+    setLimit(option.value);
+  };
+
+  const handleControllerSelection = (option: {
+    label: string;
+    value: { type: string; name: string };
+  }) => {
+    setSelectedController(option.value);
+  };
+
+  const resourceTypes = useMemo(() => {
+    if (enableNodeEvents) {
+      return [
+        { label: "Pods", value: "pod" },
+        { label: "HPA", value: "hpa" },
+        { label: "Node", value: "node" },
+      ];
+    }
+    return [
+      { label: "Pods", value: "pod" },
+      { label: "HPA", value: "hpa" },
+    ];
+  }, [enableNodeEvents]);
+
+  const controllers = useMemo(() => {
+    return availableControllers.map((c) => ({
+      label: c.name,
+      value: c,
+    }));
+  }, [availableControllers]);
+
   return (
     <div>
       <ControlRow>
-        <div>
+        <Dropdown
+          options={resourceTypes}
+          onSelect={handleResourceTypeSelection}
+        />
+        <RightFilters>
           <Dropdown
             options={[
-              { label: "Pods", value: "pod" },
-              { label: "HPA", value: "hpa" },
+              { label: "10 events", value: 10 },
+              { label: "20 events", value: 20 },
+              { label: "50 events", value: 50 },
             ]}
-            onSelect={handleEventTypeSelection}
+            onSelect={handleSetLimit}
+          />
+          <Dropdown
+            options={controllers}
+            onSelect={handleControllerSelection}
           />
-        </div>
+        </RightFilters>
       </ControlRow>
       <EventsGrid>
         {eventList.map((event) => {
@@ -140,3 +102,12 @@ const EventsGrid = styled.div`
   grid-row-gap: 15px;
   grid-template-columns: 1;
 `;
+
+const RightFilters = styled.div`
+  display: flex;
+  > div {
+    :not(:last-child) {
+      margin-right: 15px;
+    }
+  }
+`;

+ 123 - 19
dashboard/src/main/home/cluster-dashboard/expanded-chart/events/EventsTab.tsx

@@ -1,34 +1,66 @@
-import React, { useContext, useEffect, useState } from "react";
+import React from "react";
 import styled from "styled-components";
 
 import EventLogs from "components/events/EventLogs";
 import EventsList from "components/events/EventsList";
 import EventsContextProvider, {
+  Event,
   EventContext,
+  EventsContextType,
 } from "components/events/EventsContext";
+import Loading from "components/Loading";
+import loadingSrc from "assets/loading.gif";
 
 type EventsTabProps = {};
 
 const EventsTab: React.FunctionComponent<EventsTabProps> = () => {
+  const renderContent = ({
+    isLoading,
+    isPorterAgentInstalled,
+    selectedEvent,
+    installPorterAgent,
+  }: EventsContextType) => {
+    if (isLoading) {
+      return (
+        <Placeholder>
+          <div>
+            <Header>
+              <Spinner src={loadingSrc} />
+            </Header>
+          </div>
+        </Placeholder>
+      );
+    }
+
+    if (!isPorterAgentInstalled) {
+      return (
+        <Placeholder>
+          <div>
+            <Header>We coulnd't detect porter agent :(</Header>
+            In order to use the events tab you should install the porter agent!
+            <InstallPorterAgentButton onClick={() => installPorterAgent()}>
+              <i className="material-icons">add</i> Install porter agent
+            </InstallPorterAgentButton>
+          </div>
+        </Placeholder>
+      );
+    }
+
+    if (!selectedEvent) {
+      return <EventsList />;
+    }
+
+    return <EventLogs />;
+  };
+
   return (
-    <EventsContextProvider controllers={[]} enableNodeEvents={false}>
-      <EventContext.Consumer>
-        {({ selectedEvent }) => (
-          <EventsPageWrapper>
-            {!selectedEvent && (
-              <>
-                <EventsList />
-              </>
-            )}
-            {selectedEvent && (
-              <>
-                <EventLogs />
-              </>
-            )}
-          </EventsPageWrapper>
-        )}
-      </EventContext.Consumer>
-    </EventsContextProvider>
+    <EventsPageWrapper>
+      <EventsContextProvider controllers={[]} enableNodeEvents={false}>
+        <EventContext.Consumer>
+          {(context) => renderContent(context)}
+        </EventContext.Consumer>
+      </EventsContextProvider>
+    </EventsPageWrapper>
   );
 };
 
@@ -38,3 +70,75 @@ const EventsPageWrapper = styled.div`
   margin-top: 35px;
   padding-bottom: 80px;
 `;
+
+const InstallPorterAgentButton = styled.button`
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: space-between;
+  font-size: 13px;
+  cursor: pointer;
+  font-family: "Work Sans", sans-serif;
+  border: none;
+  border-radius: 20px;
+  color: white;
+  height: 35px;
+  padding: 0px 8px;
+  padding-bottom: 1px;
+  margin-top: 10px;
+  font-weight: 500;
+  padding-right: 15px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  box-shadow: 0 5px 8px 0px #00000010;
+  cursor: ${(props: { disabled?: boolean }) =>
+    props.disabled ? "not-allowed" : "pointer"};
+
+  background: ${(props: { disabled?: boolean }) =>
+    props.disabled ? "#aaaabbee" : "#616FEEcc"};
+  :hover {
+    background: ${(props: { disabled?: boolean }) =>
+      props.disabled ? "" : "#505edddd"};
+  }
+
+  > i {
+    color: white;
+    width: 18px;
+    height: 18px;
+    font-weight: 600;
+    font-size: 12px;
+    border-radius: 20px;
+    display: flex;
+    align-items: center;
+    margin-right: 5px;
+    justify-content: center;
+  }
+`;
+
+const Placeholder = styled.div`
+  min-height: 400px;
+  height: 50vh;
+  padding: 30px;
+  padding-bottom: 90px;
+  font-size: 13px;
+  color: #ffffff44;
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+`;
+
+const Header = styled.div`
+  font-weight: 500;
+  color: #aaaabb;
+  font-size: 16px;
+  margin-bottom: 15px;
+`;
+
+const Spinner = styled.img`
+  width: 15px;
+  height: 15px;
+  margin-right: 12px;
+  margin-bottom: -2px;
+`;