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

flesh out app event card with status, timestamp, logs (#3102)

* flesh out app event card with status, timestamp, logs

* undo flag change

* cleanup
Feroze Mohideen 2 лет назад
Родитель
Сommit
beabe26eb9

+ 1 - 0
dashboard/src/components/porter/Container.tsx

@@ -31,6 +31,7 @@ const StyledContainer = styled.div<{
   spaced: boolean;
 }>`
   display: ${props => props.row ? "flex" : "block"};
+  flex-direction: ${props => props.row ? "row" : "column"};
   align-items: center;
   justify-content: ${props => props.spaced ? "space-between" : "flex-start"};
 `;

+ 67 - 43
dashboard/src/main/home/app-dashboard/expanded-app/activity-feed/events/AppEventCard.tsx

@@ -1,6 +1,7 @@
 import React, { useEffect, useState } from "react";
 
 import app_event from "assets/app_event.png";
+import info from "assets/info-outlined.svg";
 
 
 import run_for from "assets/run_for.png";
@@ -11,11 +12,16 @@ import Spacer from "components/porter/Spacer";
 import Link from "components/porter/Link";
 import Icon from "components/porter/Icon";
 import Modal from "components/porter/Modal";
-import { Log } from "main/home/cluster-dashboard/expanded-chart/logs-section/useAgentLogs";
 
 import { PorterAppEvent } from "shared/types";
 import { getDuration } from './utils';
 import { StyledEventCard } from "./EventCard";
+import styled from "styled-components";
+import AppEventModal from "../../status/AppEventModal";
+import { readableDate } from "shared/string_utils";
+import dayjs from "dayjs";
+import Anser from "anser";
+import api from "shared/api";
 
 type Props = {
   event: PorterAppEvent;
@@ -24,64 +30,82 @@ type Props = {
 
 const AppEventCard: React.FC<Props> = ({ event, appData }) => {
   const [showModal, setShowModal] = useState<boolean>(false);
-  const [modalContent, setModalContent] = useState<React.ReactNode>(null);
+  const [logs, setLogs] = useState([]);
 
-  const renderStatusText = (event: PorterAppEvent) => {
-    switch (event.status) {
-      case "SUCCESS":
-        return <Text color="#68BF8B">Deployed v100</Text>;
-      case "FAILED":
-        return <Text color="#FF6060">Deploying v100 failed</Text>;
-      default:
-        return <Text color="#aaaabb66">Deploying v100...</Text>;
+  const getAppLogs = async () => {
+    setShowModal(true);
+    try {
+      const logResp = await api.getLogsWithinTimeRange(
+        "<token>",
+        {
+          namespace: appData.chart.namespace,
+          start_range: dayjs(event.created_at).toISOString(),
+          end_range: dayjs(event.updated_at).toISOString(),
+          pod_selector: event.metadata.pod_name,
+          limit: 1000,
+        },
+        {
+          project_id: appData.app.project_id,
+          cluster_id: appData.app.cluster_id,
+        }
+      )
+
+      const updatedLogs = logResp.data.logs.map((l: { line: string; timestamp: string; }, index: number) =>
+      ({
+        line: Anser.ansiToJson(l.line),
+        lineNumber: index + 1,
+        timestamp: l.timestamp,
+      }));
+
+      setLogs(updatedLogs);
+    } catch (error) {
+      console.log(error);
     }
   };
 
   return (
-    <StyledEventCard>
+    <StyledEventCard row>
       <Container row spaced>
-        <Container row>
+        <Container row spaced>
           <Icon height="18px" src={app_event} />
           <Spacer inline width="10px" />
-          <Text size={14}>Application build</Text>
-        </Container>
-        <Container row>
-          <Icon height="14px" src={run_for} />
-          <Spacer inline width="6px" />
-          <Text color="helper">{getDuration(event)}</Text>
+          <Text size={14}>{event.metadata.detail}</Text>
         </Container>
       </Container>
-      <Spacer y={1} />
       <Container row spaced>
-        <Container row>
-          {renderStatusText(event)}
-          <Link
-            hasunderline
-            onClick={() => {
-              setModalContent(
-                <>
-                  <Container row>
-                    <Icon height="20px" src={app_event} />
-                    <Spacer inline width="10px" />
-                    <Text size={16}>Event details</Text>
-                  </Container>
-                  <Spacer y={1} />
-                  <Text>TODO: display event logs</Text>
-                </>
-              );
-              setShowModal(true);
-            }}
-          >
-            View details
-          </Link>
-          <Spacer inline x={1} />
-        </Container>
+        <ViewDetailsButton onClick={getAppLogs}>
+          <Icon src={info} />
+          <Spacer inline width="6px" />
+          <Text>Details</Text>
+        </ViewDetailsButton>
       </Container>
       {showModal && (
-        <Modal closeModal={() => setShowModal(false)}>{modalContent}</Modal>
+        <AppEventModal
+          setModalVisible={setShowModal}
+          logs={logs}
+          porterAppName={appData.app.name}
+          timestamp={readableDate(event.updated_at)}
+          expandedAppEventMessage={event.metadata.summary}
+        />
       )}
     </StyledEventCard>
   );
 };
 
 export default AppEventCard;
+
+const ViewDetailsButton = styled.div<{ width?: string }>`
+  border-radius: 5px;
+  height: 30px;
+  font-size: 13px;
+  color: white;
+  display: flex;
+  align-items: center;
+  padding: 0px 10px;
+  background: #ffffff11;
+  border: 1px solid #aaaabb33;
+  cursor: pointer;
+  :hover {
+    border: 1px solid #7a7b80;
+  }
+`;

+ 2 - 2
dashboard/src/main/home/app-dashboard/expanded-app/activity-feed/events/EventCard.tsx

@@ -34,11 +34,11 @@ const EventCard: React.FC<Props> = ({ event, appData }) => {
 
 export default EventCard;
 
-export const StyledEventCard = styled.div`
+export const StyledEventCard = styled.div<{ row?: boolean }>`
   width: 100%;
   padding: 15px;
   display: flex;
-  flex-direction: column;
+  flex-direction: ${({ row }) => row ? "row" : "column"};
   justify-content: space-between;
   height: 85px;
   border-radius: 5px;

+ 1 - 1
dashboard/src/main/home/app-dashboard/expanded-app/activity-feed/events/PreDeployEventCard.tsx

@@ -93,7 +93,7 @@ const PreDeployEventCard: React.FC<Props> = ({ event, appData }) => {
           <Spacer inline width="10px" />
           {renderStatusText(event)}
           <Spacer inline x={1} />
-          <Link hasunderline onClick={() => getPredeployLogs()}>
+          <Link hasunderline onClick={getPredeployLogs}>
             View logs
           </Link>
           {event.status === "FAILED" && (

+ 79 - 0
dashboard/src/main/home/app-dashboard/expanded-app/status/AppEventModal.tsx

@@ -0,0 +1,79 @@
+import React, { useEffect, useRef } from "react";
+import Modal from "components/porter/Modal";
+import TitleSection from "components/TitleSection";
+import { Log } from "../useAgentLogs";
+import Text from "components/porter/Text";
+import danger from "assets/danger.svg";
+
+import ExpandedIncidentLogs from "./ExpandedIncidentLogs";
+import Container from "components/porter/Container";
+import Spacer from "components/porter/Spacer";
+import document from "assets/document.svg";
+import styled from "styled-components";
+import time from "assets/time.svg";
+
+interface AppEventModalProps {
+    logs: Log[];
+    setModalVisible: (x: boolean) => void;
+    porterAppName: string;
+    timestamp: string;
+    expandedAppEventMessage: string;
+}
+const AppEventModal: React.FC<AppEventModalProps> = ({ logs, porterAppName, setModalVisible, timestamp, expandedAppEventMessage }) => {
+    const scrollToBottomRef = useRef<HTMLDivElement>(null);
+    const scrollToBottom = () => {
+        if (scrollToBottomRef.current) {
+            scrollToBottomRef.current.scrollIntoView({
+                behavior: "smooth",
+                block: "end",
+            });
+        }
+    }
+    useEffect(() => {
+        scrollToBottom();
+    }, [scrollToBottomRef]);
+
+
+    return (
+        <Modal closeModal={() => setModalVisible(false)} width={"800px"}>
+            <TitleSection icon={danger}>
+                <Text size={16}>Details for {porterAppName}</Text>
+            </TitleSection>
+            <Spacer y={0.5} />
+            <Container row>
+                <Img src={time} />
+                <Spacer inline x={0.5} />
+                <Text color="helper">
+                    Last updated {timestamp}
+                </Text>
+            </Container>
+            <Spacer y={0.5} />
+            <Message>
+                <img src={document} />
+                {expandedAppEventMessage}
+            </Message>
+            <ExpandedIncidentLogs logs={logs} />
+        </Modal>
+    );
+};
+
+export default AppEventModal;
+
+const Message = styled.div`
+  padding: 20px;
+  background: #26292e;
+  border-radius: 5px;
+  line-height: 1.5em;
+  border: 1px solid #aaaabb33;
+  font-size: 13px;
+  display: flex;
+  align-items: center;
+  > img {
+    width: 13px;
+    margin-right: 20px;
+  }
+`;
+
+const Img = styled.img`
+    width: 13px;
+`;

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

@@ -213,7 +213,7 @@ const deletePorterApp = baseApi<
 
 const getLogsWithinTimeRange = baseApi<
   {
-    chart_name: string;
+    chart_name?: string;
     limit: number;
     start_range?: string;
     end_range?: string;