Procházet zdrojové kódy

Integrate paginated events (#3065)

* cache

* cache

* pagination implemented

* hide activity

* center container label

* clean up pagination component

---------

Co-authored-by: Justin Rhee <jusrhee@Justins-MacBook-Air.local>
jusrhee před 3 roky
rodič
revize
3ae5d23621

+ 2 - 1
dashboard/src/components/porter/Button.tsx

@@ -151,8 +151,9 @@ const StyledButton = styled.button<{
   border: none;
   outline: none;
   color: white;
+  opacity: ${props => props.disabled && props.withBorder ? "0.5" : "1"};
   background: ${props => {
-    if (props.alt) {
+    if (props.alt || props.color === "fg") {
       return props.theme.fg;
     }
     return (props.disabled && !props.color) ? "#aaaabb" : (props.color || props.theme.button);

+ 47 - 0
dashboard/src/components/porter/Pagination.tsx

@@ -0,0 +1,47 @@
+import React from "react";
+import styled from "styled-components";
+import Container from "./Container";
+import Text from "./Text";
+import Button from "./Button";
+import Spacer from "./Spacer";
+
+type Props = {
+  page: number;
+  setPage: (page: number) => void;
+  totalPages: number;
+};
+
+const Pagination: React.FC<Props> = ({
+  page,
+  setPage,
+  totalPages,
+}) => {
+  return (
+    <Container row spaced>
+      <Text color="helper">Viewing page {page} out of {totalPages}</Text>
+      <Container row>
+        <Button 
+          onClick={() => setPage(page - 1)} 
+          disabled={page === 1}
+          height="20px"
+          color="fg"
+          withBorder
+        >
+          Previous
+        </Button>
+        <Spacer inline x={0.5} />
+        <Button 
+          onClick={() => setPage(page + 1)}
+          disabled={page === totalPages}
+          height="20px"
+          color="fg"
+          withBorder
+        >
+          Next
+        </Button>
+      </Container>
+    </Container>
+  );
+};
+
+export default Pagination;

+ 5 - 3
dashboard/src/main/home/app-dashboard/expanded-app/ExpandedApp.tsx

@@ -743,13 +743,15 @@ const ExpandedApp: React.FC<Props> = ({ ...props }) => {
             {!appData.app.repo_name && appData.app.image_repo_uri && (
               <>
                 <Spacer inline x={1} />
-                <Text size={13} color="helper">
+                <Container row>
                   <SmallIcon
                     height="19px"
                     src="https://cdn4.iconfinder.com/data/icons/logos-and-brands/512/97_Docker_logo_logos-512.png"
                   />
-                  {appData.app.image_repo_uri}
-                </Text>
+                  <Text size={13} color="helper">
+                    {appData.app.image_repo_uri}
+                  </Text>
+                </Container>
               </>
             )}
           </Container>

+ 20 - 2
dashboard/src/main/home/app-dashboard/expanded-app/activity-feed/ActivityFeed.tsx

@@ -13,6 +13,7 @@ import Spacer from "components/porter/Spacer";
 import Fieldset from "components/porter/Fieldset";
 
 import { feedDate } from "shared/string_utils";
+import Pagination from "components/porter/Pagination";
 
 type Props = {
   chart: any;
@@ -28,6 +29,8 @@ const ActivityFeed: React.FC<Props> = ({
   const [events, setEvents] = useState<any[]>([]);
   const [loading, setLoading] = useState<boolean>(true);
   const [error, setError] = useState<any>(null);
+  const [page, setPage] = useState<number>(1);
+  const [numPages, setNumPages] = useState<number>(0);
 
   const getEvents = async () => {
     setLoading(true);
@@ -39,8 +42,10 @@ const ActivityFeed: React.FC<Props> = ({
           cluster_id: currentCluster.id,
           project_id: currentProject.id,
           stack_name: stackName,
+          page
         }
       );
+      setNumPages(res.data.num_pages);
       setEvents(res.data.events);
       setLoading(false);
     } catch (err) {
@@ -51,7 +56,7 @@ const ActivityFeed: React.FC<Props> = ({
   
   useEffect(() => {
     getEvents();
-  }, []);
+  }, [page]);
 
   if (error) {
     return (
@@ -72,6 +77,16 @@ const ActivityFeed: React.FC<Props> = ({
     );
   };
 
+  if (events?.length === 0) {
+    return (
+      <Fieldset>
+        <Text size={16}>No events found for "{stackName}"</Text>
+        <Spacer height="15px" />
+        <Text color="helper">This application currently has no associated activity.</Text>
+      </Fieldset>
+    );
+  }
+
   return (
     <StyledActivityFeed>
       {events.map((event, i) => {
@@ -84,12 +99,15 @@ const ActivityFeed: React.FC<Props> = ({
             <Dot />
             <Time>
               <Text>{feedDate(event.created_at).split(", ")[0]}</Text>
+              <Spacer x={0.5} />
               <Text>{feedDate(event.created_at).split(", ")[1]}</Text>
             </Time>
             <EventCard event={event} i={i} />
           </EventWrapper>
         );
       })}
+      <Spacer y={1} />
+      <Pagination page={page} setPage={setPage} totalPages={numPages} />
     </StyledActivityFeed>
   );
 };
@@ -97,10 +115,10 @@ const ActivityFeed: React.FC<Props> = ({
 export default ActivityFeed;
 
 const Time = styled.div`
-  margin-right: -5px;
   opacity: 0;
   animation: fadeIn 0.3s 0.1s;
   animation-fill-mode: forwards;
+  width: 90px;
 `;
 
 const Line = styled.div`

+ 3 - 2
dashboard/src/shared/api.tsx

@@ -217,10 +217,11 @@ const getFeedEvents = baseApi<
     project_id: number;
     cluster_id: number;
     stack_name: string;
+    page?: number;
   }
 >("GET", (pathParams) => {
-  let { project_id, cluster_id, stack_name } = pathParams;
-  return `/api/projects/${project_id}/clusters/${cluster_id}/stacks/${stack_name}/events`;
+  let { project_id, cluster_id, stack_name, page } = pathParams;
+  return `/api/projects/${project_id}/clusters/${cluster_id}/stacks/${stack_name}/events?page=${page || 1}`;
 });
 
 const createEnvironment = baseApi<