Sfoglia il codice sorgente

styled top-level event list + placeholder

jusrhee 4 anni fa
parent
commit
62b5de776d

+ 25 - 41
dashboard/src/components/events/EventCard.tsx

@@ -1,9 +1,6 @@
 import React, { useState } from "react";
 import styled from "styled-components";
 
-import Loading from "components/Loading";
-import { KubeEvent } from "shared/types";
-
 type CardProps = {
   event: any;
   selectEvent?: (event: any) => void;
@@ -29,7 +26,10 @@ const EventCard: React.FunctionComponent<CardProps> = ({
   const [showTooltip, setShowTooltip] = useState(false);
   return (
     <>
-      <StyledCard>
+      <StyledCard 
+        onClick={() => selectEvent(event)}
+        status={event.event_type.toLowerCase() as any}
+      >
         <ContentContainer>
           <Icon
             status={event.event_type.toLowerCase() as any}
@@ -42,23 +42,10 @@ const EventCard: React.FunctionComponent<CardProps> = ({
               <Helper>{event.resource_type}:</Helper>
               {event.name}
             </EventName>
-            <EventReason>
-              <Helper>Last message seen:</Helper>
-              {event.last_message}
-            </EventReason>
+            <EventReason>{event.last_message}</EventReason>
           </EventInformation>
         </ContentContainer>
-        <ActionContainer hasOneChild={event.event_type === "normal"}>
-          {event.sub_events?.length && (
-            <HistoryButton
-              onClick={() => selectEvent(event)}
-              onMouseEnter={() => setShowTooltip(true)}
-              onMouseLeave={() => setShowTooltip(false)}
-            >
-              <span className="material-icons-outlined">manage_search</span>
-              {showTooltip && <Tooltip>Open logs</Tooltip>}
-            </HistoryButton>
-          )}
+        <ActionContainer>
           <TimestampContainer>
             <TimestampIcon className="material-icons-outlined">
               access_time
@@ -95,21 +82,22 @@ export default EventCard;
 //   }
 // `;
 
-const StyledCard = styled.div`
+const StyledCard = styled.div<{ status: string }>`
   display: flex;
   align-items: center;
   justify-content: space-between;
-  border: 1px solid #ffffff44;
+  border: 1px solid ${({ status }) => status === "critical" ? "#ff385d" : "#ffffff44"};
   background: #ffffff08;
-  margin-bottom: 10px;
+  margin-bottom: 5px;
   border-radius: 10px;
-  padding: 20px 14px 14px 14px;
+  padding: 14px;
   overflow: hidden;
-  height: 95px;
+  height: 80px;
+  font-size: 13px;
   cursor: pointer;
   :hover {
     background: #ffffff11;
-    border: 1px solid #ffffff66;
+    border: 1px solid ${({ status }) => status === "critical" ? "#ff385d" : "#ffffff66"};
   }
   animation: fadeIn 0.5s;
   @keyframes fadeIn {
@@ -129,11 +117,11 @@ const ContentContainer = styled.div`
   align-items: center;
 `;
 
-const Icon = styled.span`
-  font-size: 35px;
-  margin-right: 14px;
-  color: ${({ status }: { status: "critical" | "normal" }) =>
-    status === "critical" ? "red" : "green"};
+const Icon = styled.span<{ status: "critical" | "normal" }>`
+  font-size: 20px;
+  margin-left: 10px;
+  margin-right: 20px;
+  color: ${({ status }) => status === "critical" ? "#ff385d" : "#aaaabb"};
 `;
 
 const EventInformation = styled.div`
@@ -144,36 +132,28 @@ const EventInformation = styled.div`
 `;
 
 const EventName = styled.div`
-  font-size: 14px;
   font-family: "Work Sans", sans-serif;
   font-weight: 500;
   color: #ffffff;
 `;
 
 const Helper = styled.span`
-  font-size: 14px;
   text-transform: capitalize;
   color: #ffffff44;
   margin-right: 5px;
 `;
 
 const EventReason = styled.div`
-  font-size: 16px;
   font-family: "Work Sans", sans-serif;
-  color: #ffffff;
-  margin-top: 8px;
+  color: #aaaabb;
+  margin-top: 5px;
 `;
 
 const ActionContainer = styled.div`
-  width: max-content;
   display: flex;
   align-items: center;
   white-space: nowrap;
   height: 100%;
-  flex-direction: column;
-  justify-content: ${(props: { hasOneChild: boolean }) => {
-    return props.hasOneChild ? "flex-end" : "space-between";
-  }};
 `;
 
 const HistoryButton = styled.button`
@@ -229,10 +209,14 @@ const TimestampContainer = styled.div`
   white-space: nowrap;
   align-items: center;
   justify-self: flex-end;
+  color: #ffffff55;
+  margin-right: 10px;
+  font-size: 13px;
   min-width: 130px;
   justify-content: space-between;
 `;
 
 const TimestampIcon = styled.span`
-  margin-right: 5px;
+  margin-right: 7px;
+  font-size: 18px;
 `;

+ 67 - 44
dashboard/src/main/home/cluster-dashboard/dashboard/events/EventsTab.tsx

@@ -60,65 +60,83 @@ const EventsTab = () => {
 
   return (
     <EventsPageWrapper>
-      <ControlRow>
-        <Dropdown
-          selectedOption={resourceType}
-          options={availableResourceTypes}
-          onSelect={(o) => setResourceType({ ...o, value: o.value as string })}
-        />
-      </ControlRow>
-
-      <InfiniteScroll
-        dataLength={kubeEvents.length}
-        next={loadMoreEvents}
-        hasMore={hasMore}
-        loader={<h4>Loading...</h4>}
-        scrollableTarget="HomeViewWrapper"
-        endMessage={
-          <h4>No events were found for the resource type you specified</h4>
-        }
-      >
-        <EventsGrid>
-          {kubeEvents.map((event, i) => {
-            return (
-              <React.Fragment key={i}>
-                <EventCard
-                  event={event}
-                  selectEvent={() => {
-                    setCurrentEvent(event);
-                  }}
-                />
-              </React.Fragment>
-            );
-          })}
-        </EventsGrid>
-      </InfiniteScroll>
+      {
+        kubeEvents.length > 0 ? (
+          <>
+            <ControlRow>
+              {/*
+              <Dropdown
+                selectedOption={resourceType}
+                options={availableResourceTypes}
+                onSelect={(o) => setResourceType({ ...o, value: o.value as string })}
+              />
+              */}
+            </ControlRow>
+            <InfiniteScroll
+              dataLength={kubeEvents.length}
+              next={loadMoreEvents}
+              hasMore={hasMore}
+              loader={<h4>Loading...</h4>}
+              scrollableTarget="HomeViewWrapper"
+            >
+              <EventsGrid>
+                {kubeEvents.map((event, i) => {
+                  return (
+                    <React.Fragment key={i}>
+                      <EventCard
+                        event={event}
+                        selectEvent={() => setCurrentEvent(event)}
+                      />
+                    </React.Fragment>
+                  );
+                })}
+              </EventsGrid>
+            </InfiniteScroll>
+          </>
+        ) : (
+          <Placeholder>
+            <i className="material-icons">search</i>
+            No matching events were found.
+          </Placeholder>
+        )
+      }
     </EventsPageWrapper>
   );
 };
 
 export default EventsTab;
 
-const RightFilters = styled.div`
-  display: flex;
-  > div {
-    :not(:last-child) {
-      margin-right: 15px;
-    }
-  }
+const Label = styled.div`
+  color: #ffffff44;
+  margin-right: 8px;
+  font-size: 13px;
 `;
 
 const ControlRow = styled.div`
   display: flex;
-  justify-content: space-between;
   align-items: center;
-  margin-bottom: 35px;
+  margin-bottom: 30px;
   padding-left: 0px;
+  font-size: 13px;
 `;
 
 const EventsPageWrapper = styled.div`
-  margin-top: 35px;
+  font-size: 13px;
   padding-bottom: 80px;
+  border-radius: 8px;
+  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 EventsGrid = styled.div`
@@ -178,11 +196,16 @@ const Placeholder = styled.div`
   min-height: 400px;
   height: 50vh;
   background: #ffffff11;
-  border-radius: 10px;
+  border-radius: 8px;
   width: 100%;
   display: flex;
   align-items: center;
   justify-content: center;
+
+  > i {
+    font-size: 18px;
+    margin-right: 8px;
+  }
 `;
 
 const Header = styled.div`

+ 195 - 52
dashboard/src/main/home/cluster-dashboard/expanded-chart/events/EventsTab.tsx

@@ -14,6 +14,125 @@ 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) => {
@@ -93,72 +212,91 @@ const EventsTab: React.FC<{
 
   return (
     <EventsPageWrapper>
-      <ControlRow>
-        <Dropdown
-          selectedOption={resourceType}
-          options={availableResourceTypes}
-          onSelect={(o) => setResourceType({ ...o, value: o.value as string })}
-        />
-        <RightFilters>
-          <Dropdown
-            selectedOption={currentControllerOption}
-            options={controllerOptions}
-            onSelect={(o) => setSelectedControllerKey(o?.value)}
-          />
-        </RightFilters>
-      </ControlRow>
-
-      <InfiniteScroll
-        dataLength={kubeEvents.length}
-        next={loadMoreEvents}
-        hasMore={hasMore}
-        loader={<h4>Loading...</h4>}
-        scrollableTarget="HomeViewWrapper"
-        endMessage={
-          <h4>No events were found for the resource type you specified</h4>
-        }
-      >
-        <EventsGrid>
-          {kubeEvents.map((event, i) => {
-            return (
-              <React.Fragment key={i}>
-                <EventCard
-                  event={event as any}
-                  selectEvent={() => {
-                    setCurrentEvent(event);
-                  }}
-                />
-              </React.Fragment>
-            );
-          })}
-        </EventsGrid>
-      </InfiniteScroll>
+      {
+        kubeEvents.length > 0 ? (
+          <>
+            <ControlRow>
+              {/*
+              <Dropdown
+                selectedOption={resourceType}
+                options={availableResourceTypes}
+                onSelect={(o) => setResourceType({ ...o, value: o.value as string })}
+              />
+              */}
+              <Label>Controller -</Label>
+              <Dropdown
+                selectedOption={currentControllerOption}
+                options={controllerOptions}
+                onSelect={(o) => setSelectedControllerKey(o?.value)}
+              />
+            </ControlRow>
+
+            <InfiniteScroll
+              dataLength={kubeEvents.length}
+              next={loadMoreEvents}
+              hasMore={hasMore}
+              loader={<h4>Loading...</h4>}
+              scrollableTarget="HomeViewWrapper"
+            >
+              <EventsGrid>
+                {kubeEvents.map((event, i) => {
+                  return (
+                    <React.Fragment key={i}>
+                      <EventCard
+                        event={event as any}
+                        selectEvent={() => {
+                          setCurrentEvent(event);
+                        }}
+                      />
+                    </React.Fragment>
+                  );
+                })}
+              </EventsGrid>
+            </InfiniteScroll>
+          </>
+        ) : (
+          <Placeholder>
+            <i className="material-icons">search</i>
+            No matching events were found.
+          </Placeholder>
+        )
+      }
     </EventsPageWrapper>
   );
 };
 
 export default EventsTab;
 
-const RightFilters = styled.div`
-  display: flex;
-  > div {
-    :not(:last-child) {
-      margin-right: 15px;
-    }
-  }
+const Label = styled.div`
+  color: #ffffff44;
+  margin-right: 8px;
+  font-size: 13px;
 `;
 
 const ControlRow = styled.div`
   display: flex;
-  justify-content: space-between;
   align-items: center;
-  margin-bottom: 35px;
+  margin-bottom: 30px;
   padding-left: 0px;
+  font-size: 13px;
 `;
 
 const EventsPageWrapper = styled.div`
-  margin-top: 35px;
-  padding-bottom: 80px;
+  font-size: 13px;
+  border-radius: 8px;
+  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 EventsGrid = styled.div`
@@ -217,11 +355,16 @@ const Placeholder = styled.div`
   min-height: 400px;
   height: 50vh;
   background: #ffffff11;
-  border-radius: 10px;
+  border-radius: 8px;
   width: 100%;
   display: flex;
   align-items: center;
   justify-content: center;
+
+  > i {
+    font-size: 18px;
+    margin-right: 8px;
+  }
 `;
 
 const Header = styled.div`