jusrhee 4 лет назад
Родитель
Сommit
c9b48fae29

+ 1 - 23
dashboard/src/components/events/EventCard.tsx

@@ -28,7 +28,7 @@ const EventCard: React.FunctionComponent<CardProps> = ({
     <>
       <StyledCard 
         onClick={() => selectEvent(event)}
-        status={event.event_type.toLowerCase() as any}
+        status={event.event_type.toLowerCase()}
       >
         <ContentContainer>
           <Icon
@@ -60,28 +60,6 @@ const EventCard: React.FunctionComponent<CardProps> = ({
 
 export default EventCard;
 
-// const StyledCard = styled.div`
-//   background: #26282f;
-//   min-height: 100px;
-//   width: 100%;
-//   display: flex;
-
-//   align-items: center;
-//   border: 1px solid #26282f;
-//   box-shadow: 0 4px 15px 0px #00000055;
-//   border-radius: 8px;
-//   padding: 14px;
-//   animation: fadeIn 0.5s;
-//   @keyframes fadeIn {
-//     from {
-//       opacity: 0;
-//     }
-//     to {
-//       opacity: 1;
-//     }
-//   }
-// `;
-
 const StyledCard = styled.div<{ status: string }>`
   display: flex;
   align-items: center;

+ 169 - 25
dashboard/src/components/events/SubEventsList.tsx

@@ -7,6 +7,16 @@ import SubEventCard from "./sub-events/SubEventCard";
 import Loading from "components/Loading";
 import LogBucketCard from "./sub-events/LogBucketCard";
 
+const getReadableDate = (s: number) => {
+  let ts = new Date(s);
+  let date = ts.toLocaleDateString();
+  let time = ts.toLocaleTimeString([], {
+    hour: "numeric",
+    minute: "2-digit",
+  });
+  return `${time} ${date}`;
+};
+
 const SubEventsList: React.FC<{
   clearSelectedEvent: () => void;
   event: any;
@@ -94,53 +104,193 @@ const SubEventsList: React.FC<{
   }, [subEvents]);
 
   return (
-    <>
+    <Timeline>
       <ControlRow>
-        <div>
-          <BackButton onClick={clearSelectedEvent}>
-            <BackButtonImg src={backArrow} />
-          </BackButton>
-        </div>
+        <BackButton onClick={clearSelectedEvent}>
+          <i className="material-icons">close</i>
+        </BackButton>
+        <Icon
+          status={event.event_type.toLowerCase() as any}
+          className="material-icons-outlined"
+        >
+          {event.event_type === "critical" ? "report_problem" : "info"}
+        </Icon>
+        Pod {event.name} crashed
       </ControlRow>
       {isLoading ? (
-        <Loading />
+        <Placeholder>
+          <Loading />
+        </Placeholder>
       ) : sortedSubEvents?.length ? (
         <EventsGrid>
-          {sortedSubEvents.map((subEvent: any) => {
+          <Rail />
+          {sortedSubEvents.map((subEvent: any, i: number) => {
             if (subEvent?.event_type === "log_bucket") {
-              return <LogBucketCard logEvent={subEvent} />;
+              return (
+                <Wrapper>
+                  <TimelineNode>
+                    <Penumbra>
+                      <Circle />
+                    </Penumbra>
+                    {getReadableDate(subEvent.timestamp)}
+                  </TimelineNode>
+                  <LogBucketCard logEvent={subEvent} />
+                  {i === sortedSubEvents.length - 1 && (
+                    <RailCover />
+                  )}
+                </Wrapper>
+              );
             }
-            return <SubEventCard subEvent={subEvent} />;
+            return (
+              <Wrapper>
+                <TimelineNode>
+                  <Penumbra>
+                    <Circle />
+                  </Penumbra>
+                  {getReadableDate(subEvent.timestamp)}
+                </TimelineNode>
+                <SubEventCard subEvent={subEvent} />
+                {i === sortedSubEvents.length - 1 && (
+                  <RailCover />
+                )}
+              </Wrapper>
+            );
           })}
         </EventsGrid>
       ) : (
-        "No sub events found for this resource "
+        <Placeholder>
+          <i className="material-icons">search</i>
+          No sub-events were found.
+        </Placeholder>
       )}
-    </>
+    </Timeline>
   );
 };
 
 export default SubEventsList;
 
+const Placeholder = styled.div`
+  padding: 30px;
+  padding-bottom: 40px;
+  font-size: 13px;
+  color: #ffffff44;
+  min-height: 340px;
+  margin-top: 20px;
+  background: #ffffff08;
+  height: calc(50vh - 60px);
+  border-radius: 8px;
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  > i {
+    font-size: 18px;
+    margin-right: 8px;
+  }
+`;
+
+const RailCover = styled.div`
+  background: #202227;
+  height: 100%;
+  width: 35px;
+  position: absolute;
+  top: 20px;
+  left: 0;
+`;
+
+const Penumbra = styled.div`
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #202227;
+  padding: 8px;
+  border-radius: 30px;
+  margin-right: 4px;
+`;
+
+const TimelineNode = styled.div`
+  position: absolute;
+  top: 0;
+  left: 7px;
+  display: flex;
+  align-items: center;
+  color: #aaaabb;
+  font-size: 13px;
+`;
+
+const Circle = styled.div`
+  width: 7px;
+  height: 7px;
+  border-radius: 20px;
+  background: #aaaabb;
+`;
+
+const Wrapper = styled.div`
+  position: relative;
+  width: 100%;
+  padding-top: 35px;
+  padding-left: 35px;
+`;
+
+const Rail = styled.div`
+  position: absolute;
+  top: -8px;
+  left: 17px;
+  width: 3px;
+  height: 100%;
+  z-index: -1;
+  background: #36383D;
+`;
+
+const Timeline = styled.div`
+  animation: floatIn 0.3s;
+  animation-timing-function: ease-out;
+  animation-fill-mode: forwards;
+  @keyframes floatIn {
+    from {
+      opacity: 0;
+      transform: translateY(10px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0px);
+    }
+  }
+`;
+
+const Icon = styled.span<{ status: "critical" | "normal" }>`
+  font-size: 26px;
+  margin-left: 17px;
+  margin-right: 10px;
+  color: ${({ status }) => status === "critical" ? "#ff385d" : "#aaaabb"};
+`;
+
 const ControlRow = styled.div`
   display: flex;
-  justify-content: space-between;
+  justify-content: flex-start;
   align-items: center;
-  margin-top: 35px;
-  margin-bottom: 35px;
+  margin-bottom: 15px;
   padding-left: 0px;
+  font-weight: 500;
 `;
 
 const BackButton = styled.div`
   display: flex;
-  width: 36px;
+  width: 37px;
+  z-index: 1;
   cursor: pointer;
-  height: 36px;
+  height: 37px;
   align-items: center;
   justify-content: center;
   border: 1px solid #ffffff55;
   border-radius: 100px;
   background: #ffffff11;
+
+  > i {
+    font-size: 20px;
+  }
+
   :hover {
     background: #ffffff22;
     > img {
@@ -149,13 +299,7 @@ const BackButton = styled.div`
   }
 `;
 
-const BackButtonImg = styled.img`
-  width: 16px;
-  opacity: 0.75;
-`;
-
 const EventsGrid = styled.div`
-  display: grid;
-  grid-row-gap: 15px;
-  grid-template-columns: 1;
+  position: relative;
+  padding-top: 9px;
 `;

+ 37 - 78
dashboard/src/components/events/sub-events/LogBucketCard.tsx

@@ -53,97 +53,56 @@ const LogBucketCard: React.FunctionComponent<LogBucketCardProps> = ({
 
   return (
     <StyledCard>
-      <div style={{ display: "flex", alignItems: "center" }}>
-        <Icon className="material-icons-outlined">info</Icon>
-        <InfoWrapper>
-          <div>
-            <EventName>Logs for: {logEvent.resource_name}</EventName>
-          </div>
-        </InfoWrapper>
-      </div>
-      <InfoWrapper>
-        <TimestampContainer>
-          <i className="material-icons-outlined">access_time</i>
-          {getReadableDate(logEvent.timestamp)}
-        </TimestampContainer>
-        <button onClick={() => setIsExpanded((expanded) => !expanded)}>
-          Show more
-        </button>
-      </InfoWrapper>
-
       {/* Case: Is still getting logs and user triggered expanded */}
-      {isExpanded && isLoading && "Loading"}
+      {isLoading && (
+        <Loading>Loading . . .</Loading>
+      )}
       {/* Case: No logs found after the api call */}
-      {isExpanded && !isLoading && !logs?.length && "No logs found"}
+      {!isLoading && !logs?.length && (
+        <Loading>No logs found.</Loading>
+      )}
       {/* Case: Logs were found successfully  */}
-      {isExpanded &&
-        !isLoading &&
+      {!isLoading &&
         logs?.length &&
-        logs?.map((l) => <span>{l}</span>)}
+        logs?.map((l) => <Log>{l}</Log>)}
     </StyledCard>
   );
 };
 
 export default LogBucketCard;
 
-const StyledCard = styled.div`
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  border: 1px solid #ffffff44;
-  background: #ffffff08;
-  margin-bottom: 10px;
-  border-radius: 10px;
-  padding-left: 20px;
-  padding-right: 20px;
-  overflow: hidden;
-  height: 80px;
-  cursor: pointer;
-  justify-content: space-between;
-
-  :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"};
-`;
-
-const InfoWrapper = styled.div`
-  display: flex;
-  flex-direction: column;
+const Loading = styled.div`
+  margin-top: 5px;
+  margin-left: 5px;
 `;
 
-const EventName = styled.div`
-  font-size: 13px;
-  font-family: "Work Sans", sans-serif;
-  font-weight: 500;
-  color: #ffffff;
+const Log = styled.div`
+  font-family: monospace, sans-serif;
+  font-size: 12px;
+  color: white;
 `;
 
-const TimestampContainer = styled.div`
-  display: flex;
-  align-items: center;
-  color: #ffffff55;
+const StyledCard = styled.div`
+  border: 1px solid #ffffff44;
+  margin-bottom: 30px;
+  border-radius: 10px;
+  padding: 14px;
+  padding-left: 13px;
   font-size: 13px;
-  margin-top: 8px;
-  justify-self: flex-end;
-
-  > i {
-    margin-right: 5px;
-    font-size: 18px;
-    margin-left: -1px;
+  background: #121318;
+  user-select: text;
+  overflow-wrap: break-word;
+  overflow-y: auto;
+  min-height: 55px;
+  color: #aaaabb;
+
+  animation: fadeIn 0.5s;
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 1;
+    }
   }
-`;
-
-const EventReason = styled.div`
-  font-size: 16px;
-  font-family: "Work Sans", sans-serif;
-  color: #ffffff;
-  margin-top: 8px;
-`;
+`;

+ 31 - 89
dashboard/src/components/events/sub-events/SubEventCard.tsx

@@ -5,112 +5,54 @@ type CardProps = {
   subEvent: any;
 };
 
-const getReadableDate = (s: number) => {
-  let ts = new Date(s);
-  let date = ts.toLocaleDateString();
-  let time = ts.toLocaleTimeString([], {
-    hour: "numeric",
-    minute: "2-digit",
-  });
-  return `${time} ${date}`;
-};
-
 const SubEventCard: React.FunctionComponent<CardProps> = ({ subEvent }) => {
   return (
-    <StyledCard>
-      <div style={{ display: "flex", alignItems: "center" }}>
-        <Icon
-          status={subEvent.event_type.toLowerCase() as any}
-          className="material-icons-outlined"
-        >
-          {subEvent.event_type.toLowerCase() === "critical"
-            ? "report_problem"
-            : "info"}
-        </Icon>
-        <InfoWrapper>
-          <div>
-            <EventName>Event type: {subEvent.event_type}</EventName>
-            <EventReason>Detail: {subEvent.message}</EventReason>
-          </div>
-        </InfoWrapper>
-      </div>
-      <TimestampContainer>
-        <i className="material-icons-outlined">access_time</i>
-        {getReadableDate(subEvent.timestamp)}
-      </TimestampContainer>
+    <StyledCard
+      status={subEvent.event_type.toLowerCase()}
+    >
+      <Icon
+        status={subEvent.event_type.toLowerCase() as any}
+        className="material-icons-outlined"
+      >
+        {subEvent.event_type.toLowerCase() === "critical"
+          ? "report_problem"
+          : "info"}
+      </Icon>
+      {subEvent.message}
     </StyledCard>
   );
 };
 
 export default SubEventCard;
 
-const StyledCard = styled.div`
+const StyledCard = styled.div<{ status: string }>`
   display: flex;
-  flex-direction: row;
   align-items: center;
-  border: 1px solid #ffffff44;
+  justify-content: flex-start;
+  border: 1px solid ${({ status }) => status === "critical" ? "#ff385d" : "#ffffff44"};
   background: #ffffff08;
-  margin-bottom: 10px;
+  margin-bottom: 30px;
   border-radius: 10px;
-  padding-left: 20px;
-  padding-right: 20px;
+  padding: 14px;
+  padding-left: 13px;
   overflow: hidden;
-  height: 80px;
-  cursor: pointer;
-  justify-content: space-between;
-
-  :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 {
+  height: 55px;
+  font-size: 13px;
+  color: #aaaabb;
+  animation: fadeIn 0.5s;
+  @keyframes fadeIn {
     from {
-      transform: rotate(0deg);
+      opacity: 0;
     }
     to {
-      transform: rotate(360deg);
+      opacity: 1;
     }
   }
 `;
 
-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;
-  justify-self: flex-end;
-
-  > i {
-    margin-right: 5px;
-    font-size: 18px;
-    margin-left: -1px;
-  }
-`;
-
-const EventReason = styled.div`
-  font-size: 16px;
-  font-family: "Work Sans", sans-serif;
-  color: #ffffff;
-  margin-top: 8px;
-`;
+const Icon = styled.span<{ status: "critical" | "normal" }>`
+  font-size: 20px;
+  margin-left: 10px;
+  margin-right: 13px;
+  color: ${({ status }) => status === "critical" ? "#ff385d" : "#aaaabb"};
+`;

+ 4 - 124
dashboard/src/main/home/cluster-dashboard/expanded-chart/events/EventsTab.tsx

@@ -14,125 +14,6 @@ const availableResourceTypes = [
   { label: "HPA", value: "hpa" },
 ];
 
-const fakeKubeEvents = [
-  {
-    event_type: "normal",
-    resource_type: "pod",
-    name: "some-resource-name",
-    last_message: "This is the last message I sent randomly",
-    sub_events: [
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-    ] as any[],
-    timestamp: "2021-11-12T22:23:21+00:00"
-  },
-  {
-    event_type: "critical",
-    resource_type: "pod",
-    name: "some-resource-name",
-    last_message: "This is the last message I sent randomly",
-    sub_events: [
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-    ] as any[],
-    timestamp: "2021-11-12T22:23:21+00:00"
-  },
-  {
-    event_type: "normal",
-    resource_type: "pod",
-    name: "some-resource-name",
-    last_message: "This is the last message I sent randomly",
-    sub_events: [
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-    ] as any[],
-    timestamp: "2021-11-12T22:23:21+00:00"
-  },
-  {
-    event_type: "normal",
-    resource_type: "pod",
-    name: "some-resource-name",
-    last_message: "This is the last message I sent randomly",
-    sub_events: [
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-      {
-        event_type: "normal",
-        resource_type: "pod",
-        name: "some-resource-name",
-        last_message: "This is the last message I sent randomly",
-        sub_events: [] as any[],
-        timestamp: "2021-11-12T22:23:21+00:00"
-      },
-    ] as any[],
-    timestamp: "2021-11-12T22:23:21+00:00"
-  },
-  {
-    event_type: "normal",
-    resource_type: "pod",
-    name: "some-resource-name",
-    last_message: "This is the last message I sent randomly",
-    sub_events: [] as any[],
-    timestamp: "2021-11-12T22:23:21+00:00"
-  },
-  {
-    event_type: "normal",
-    resource_type: "pod",
-    name: "some-resource-name",
-    last_message: "This is the last message I sent randomly",
-    sub_events: [] as any[],
-    timestamp: "2021-11-12T22:23:21+00:00"
-  },
-]
-
 const EventsTab: React.FC<{
   controllers: Record<string, Record<string, any>>;
 }> = (props) => {
@@ -162,7 +43,6 @@ const EventsTab: React.FC<{
 
   const selectedController = controllers[currentControllerOption?.value];
 
-  console.log(controllers, currentControllerOption);
   const {
     isLoading,
     hasPorterAgent,
@@ -213,7 +93,7 @@ const EventsTab: React.FC<{
   return (
     <EventsPageWrapper>
       {
-        fakeKubeEvents.length > 0 ? (
+        kubeEvents.length > 0 ? (
           <>
             <ControlRow>
               {/*
@@ -232,14 +112,14 @@ const EventsTab: React.FC<{
             </ControlRow>
 
             <InfiniteScroll
-              dataLength={fakeKubeEvents.length}
+              dataLength={kubeEvents.length}
               next={loadMoreEvents}
               hasMore={hasMore}
               loader={<h4>Loading...</h4>}
               scrollableTarget="HomeViewWrapper"
             >
               <EventsGrid>
-                {fakeKubeEvents.map((event, i) => {
+                {kubeEvents.map((event, i) => {
                   return (
                     <React.Fragment key={i}>
                       <EventCard
@@ -354,7 +234,7 @@ const Placeholder = styled.div`
   color: #ffffff44;
   min-height: 400px;
   height: 50vh;
-  background: #ffffff11;
+  background: #ffffff08;
   border-radius: 8px;
   width: 100%;
   display: flex;

+ 18 - 6
dashboard/src/main/home/navbar/Help.tsx

@@ -77,7 +77,7 @@ export default class Help extends Component<PropsType, StateType> {
 Help.contextType = Context;
 
 const Option = styled.div`
-  margin-left: 15px;
+  margin-left: 12px;
   font-size: 13px;
   display: flex;
   align-items: center;
@@ -89,10 +89,22 @@ const Option = styled.div`
   > i {
     opacity: 50%;
     color: white;
-    margin-right: 7px;
-    font-size: 20px;
+    margin-right: 9px;
+    font-size: 18px;
     cursor: pointer;
   }
+
+  :hover {
+    color: #ffffff;
+    
+    > img {
+      opacity: 100%;
+    }
+
+    > i {
+      opacity: 100%;
+    }
+  }
 `;
 
 const Line = styled.div`
@@ -204,8 +216,8 @@ const FeedbackButton = styled(NavButton)`
 
 const Icon = styled.img`
   margin-left: -2px;
-  height: 25px;
-  width: 25px;
+  height: 22px;
+  width: 22px;
   opacity: 50%;
-  margin-right: 5px;
+  margin-right: 7px;
 `;

+ 2 - 1
dashboard/src/main/home/sidebar/Sidebar.tsx

@@ -315,11 +315,12 @@ class Sidebar extends Component<PropsType, StateType> {
           <br />
 
           {this.renderProjectContents()}
-
+          {/*
           <DiscordButton href="https://discord.gg/34n7NN7FJ7" target="_blank">
             <Icon src={discordLogo} />
             Join Our Discord
           </DiscordButton>
+          */}
         </StyledSidebar>
       </>
     );