Просмотр исходного кода

Hoisted out dropdown to improve readability

jnfrati 4 лет назад
Родитель
Сommit
5c696cc67d

+ 154 - 0
dashboard/src/components/Dropdown.tsx

@@ -0,0 +1,154 @@
+import React, { useState } from "react";
+import styled from "styled-components";
+
+type Option = {
+  value: unknown;
+  label: string;
+};
+
+type DropdownProps = {
+  options: Array<Option>;
+  onSelect: (selectedOption: Option) => unknown;
+  selectLabel?: (currentLabel: string) => void;
+  selectValue?: (currentValue: any) => void;
+};
+
+const Dropdown: React.FunctionComponent<DropdownProps> = ({
+  options,
+  selectLabel,
+  selectValue,
+  onSelect,
+}) => {
+  const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
+  const [selectedOption, setSelectedOption] = useState<Option>(options[0]);
+
+  const handleSelectOption = (option: Option) => {
+    setSelectedOption(option);
+    onSelect(option);
+    typeof selectLabel === "function" && selectLabel(option.label);
+    typeof selectValue === "function" && selectValue(option.value);
+  };
+
+  const renderDropdown = () => {
+    if (isDropdownExpanded) {
+      return (
+        <>
+          <DropdownOverlay onClick={() => setIsDropdownExpanded(false)} />
+          <OptionWrapper
+            dropdownWidth="230px"
+            dropdownMaxHeight="200px"
+            onClick={() => setIsDropdownExpanded(false)}
+          >
+            {renderOptionList()}
+          </OptionWrapper>
+        </>
+      );
+    }
+  };
+
+  const renderOptionList = () => {
+    return options.map((option, i, originalArray) => {
+      return (
+        <Option
+          key={i}
+          selected={option.label === selectedOption.label}
+          onClick={() => handleSelectOption(option)}
+          lastItem={i === originalArray.length - 1}
+        >
+          {option.label}
+        </Option>
+      );
+    });
+  };
+
+  return (
+    <DropdownSelector
+      onClick={() => setIsDropdownExpanded(!isDropdownExpanded)}
+    >
+      <DropdownLabel>{selectedOption?.label}</DropdownLabel>
+      <i className="material-icons">arrow_drop_down</i>
+      {renderDropdown()}
+    </DropdownSelector>
+  );
+};
+
+export default Dropdown;
+
+const DropdownSelector = styled.div`
+  font-size: 13px;
+  font-weight: 500;
+  position: relative;
+  color: #ffffff;
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  border-radius: 5px;
+  :hover {
+    > i {
+      background: #ffffff22;
+    }
+  }
+
+  > i {
+    border-radius: 20px;
+    font-size: 20px;
+    margin-left: 10px;
+  }
+`;
+
+const DropdownLabel = styled.div`
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  max-width: 200px;
+`;
+
+const DropdownOverlay = styled.div`
+  position: fixed;
+  width: 100%;
+  height: 100%;
+  z-index: 10;
+  left: 0px;
+  top: 0px;
+  cursor: default;
+`;
+
+const OptionWrapper = styled.div`
+  position: absolute;
+  left: 0;
+  top: calc(100% + 10px);
+  background: #26282f;
+  width: ${(props: { dropdownWidth: string; dropdownMaxHeight: string }) =>
+    props.dropdownWidth};
+  max-height: ${(props: { dropdownWidth: string; dropdownMaxHeight: string }) =>
+    props.dropdownMaxHeight || "300px"};
+  border-radius: 3px;
+  z-index: 999;
+  overflow-y: auto;
+  margin-bottom: 20px;
+  box-shadow: 0px 4px 10px 0px #00000088;
+`;
+
+const Option = styled.div`
+  width: 100%;
+  border-top: 1px solid #00000000;
+  border-bottom: 1px solid
+    ${(props: { selected: boolean; lastItem: boolean }) =>
+      props.lastItem ? "#ffffff00" : "#ffffff15"};
+  height: 37px;
+  font-size: 13px;
+  padding-top: 9px;
+  align-items: center;
+  padding-left: 15px;
+  cursor: pointer;
+  padding-right: 10px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  background: ${(props: { selected: boolean; lastItem: boolean }) =>
+    props.selected ? "#ffffff11" : ""};
+
+  :hover {
+    background: #ffffff22;
+  }
+`;

+ 0 - 1
dashboard/src/components/EventLogs.tsx

@@ -3,7 +3,6 @@ import React from "react";
 
 type EventLogsProps = {
   event: Event;
-  goBack: () => void;
 };
 
 const EventLogs: React.FunctionComponent<EventLogsProps> = ({}) => {

+ 77 - 21
dashboard/src/main/home/cluster-dashboard/expanded-chart/events/EventsTab.tsx

@@ -1,7 +1,9 @@
-import EventCard from "components/EventCard";
-import EventLogs from "components/EventLogs";
 import React, { useEffect, useState } from "react";
 import styled from "styled-components";
+import backArrow from "assets/back_arrow.png";
+import Dropdown from "components/Dropdown";
+import EventCard from "components/EventCard";
+import EventLogs from "components/EventLogs";
 
 const mockData = [
   {
@@ -110,12 +112,17 @@ type EventsTabProps = {};
 const EventsTab: React.FunctionComponent<EventsTabProps> = () => {
   const [eventList, setEventList] = useState<Event[]>([]);
   const [selectedEvent, setSelectedEvent] = useState<Event>(null);
+  const [currentFilter, setCurrentFilter] = useState<string>("all");
 
   useEffect(() => {
     setTimeout(() => {
-      setEventList(mockData as Event[]);
+      setEventList(
+        (mockData as Event[]).filter(
+          (e) => currentFilter === "all" || e.resource_type === currentFilter
+        )
+      );
     }, 500);
-  }, []);
+  }, [currentFilter]);
 
   const selectEvent = (id: number) => {
     const event = eventList.find((e) => e.id === id);
@@ -126,29 +133,54 @@ const EventsTab: React.FunctionComponent<EventsTabProps> = () => {
     setSelectedEvent(null);
   };
 
+  const handleEventTypeSelection = (option: {
+    label: string;
+    value: string;
+  }) => {
+    console.log(option);
+    setCurrentFilter(option.value);
+  };
+
   return (
     <NamespaceListWrapper>
-      <ControlRow>
-        <button>
-          <i className="material-icons">add</i> Add namespace
-        </button>
-      </ControlRow>
-
       {!selectedEvent && (
-        <EventsGrid>
-          {eventList.map((event) => {
-            return (
-              <EventCard
-                key={event.id}
-                event={event}
-                selectEvent={selectEvent}
+        <>
+          <ControlRow>
+            <div>
+              <Dropdown
+                options={[
+                  { label: "All", value: "all" },
+                  { label: "Pods", value: "pod" },
+                  { label: "HPA", value: "HPA" },
+                ]}
+                onSelect={handleEventTypeSelection}
               />
-            );
-          })}
-        </EventsGrid>
+            </div>
+          </ControlRow>
+          <EventsGrid>
+            {eventList.map((event) => {
+              return (
+                <EventCard
+                  key={event.id}
+                  event={event}
+                  selectEvent={selectEvent}
+                />
+              );
+            })}
+          </EventsGrid>
+        </>
       )}
       {selectedEvent && (
-        <EventLogs event={selectedEvent} goBack={clearSelectedEvent} />
+        <>
+          <ControlRow>
+            <div>
+              <BackButton onClick={clearSelectedEvent}>
+                <BackButtonImg src={backArrow} />
+              </BackButton>
+            </div>
+          </ControlRow>
+          <EventLogs event={selectedEvent} />
+        </>
       )}
     </NamespaceListWrapper>
   );
@@ -174,3 +206,27 @@ const EventsGrid = styled.div`
   grid-row-gap: 15px;
   grid-template-columns: 1;
 `;
+
+const BackButton = styled.div`
+  display: flex;
+  width: 36px;
+  cursor: pointer;
+  height: 36px;
+  align-items: center;
+  justify-content: center;
+  border: 1px solid #ffffff55;
+  border-radius: 100px;
+  background: #ffffff11;
+
+  :hover {
+    background: #ffffff22;
+    > img {
+      opacity: 1;
+    }
+  }
+`;
+
+const BackButtonImg = styled.img`
+  width: 16px;
+  opacity: 0.75;
+`;