sdess09 2 роки тому
батько
коміт
970f76f6ba

+ 3 - 0
dashboard/src/assets/copy-left.svg

@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18 9.5999H20.4C21.0628 9.5999 21.6 10.1372 21.6 10.7999L21.6 19.5999C21.6 20.7045 20.7046 21.5999 19.6 21.5999L10.8 21.5999C10.1373 21.5999 9.60003 21.0626 9.60003 20.3999V17.9999M12 2.3999L4.80003 2.3999C3.47454 2.3999 2.40003 3.47442 2.40003 4.7999L2.40002 11.9999C2.40002 13.3254 3.47454 14.3999 4.80002 14.3999L12 14.3999C13.3255 14.3999 14.4 13.3254 14.4 11.9999L14.4 4.7999C14.4 3.47442 13.3255 2.3999 12 2.3999Z" stroke="white" stroke-width="2" stroke-linecap="round"/>
+</svg>

+ 16 - 17
dashboard/src/main/home/app-dashboard/expanded-app/env-vars/EnvGroupModal.tsx

@@ -66,11 +66,11 @@ const EnvGroupModal: React.FC<Props> = ({
           "<token>",
           "<token>",
           {},
           {},
           {
           {
-            id: currentProject.id,
-            cluster_id: currentCluster.id,
+            id: currentProject?.id,
+            cluster_id: currentCluster?.id,
           }
           }
         )
         )
-        .then((res) => res.data.environment_groups);
+        .then((res) => res.data?.environment_groups);
     } catch (error) {
     } catch (error) {
       setLoading(false)
       setLoading(false)
       setError(true);
       setError(true);
@@ -114,27 +114,26 @@ const EnvGroupModal: React.FC<Props> = ({
         </LoadingWrapper>
         </LoadingWrapper>
       );
       );
     } else {
     } else {
-      const sortedEnvGroups = envGroups.slice().sort((a, b) => a.name.localeCompare(b.name));
-
-      return sortedEnvGroups
-        .filter((envGroup) => {
-          if (!Array.isArray(syncedEnvGroups)) {
-            return true;
-          }
-          return !syncedEnvGroups.find(
-            (syncedEnvGroup) => syncedEnvGroup.name === envGroup.name
-          );
-        })
+      const sortedEnvGroups = envGroups?.slice().sort((a, b) => a.name.localeCompare(b.name));
+
+      return sortedEnvGroups?.filter((envGroup) => {
+        if (!Array.isArray(syncedEnvGroups)) {
+          return true;
+        }
+        return !syncedEnvGroups?.find(
+          (syncedEnvGroup) => syncedEnvGroup?.name === envGroup?.name
+        );
+      })
         .map((envGroup: any, i: number) => {
         .map((envGroup: any, i: number) => {
           return (
           return (
             <EnvGroupRow
             <EnvGroupRow
               key={i}
               key={i}
               isSelected={selectedEnvGroup === envGroup}
               isSelected={selectedEnvGroup === envGroup}
-              lastItem={i === envGroups.length - 1}
+              lastItem={i === envGroups?.length - 1}
               onClick={() => setSelectedEnvGroup(envGroup)}
               onClick={() => setSelectedEnvGroup(envGroup)}
             >
             >
               <img src={sliders} />
               <img src={sliders} />
-              {envGroup.name}
+              {envGroup?.name}
             </EnvGroupRow>
             </EnvGroupRow>
           );
           );
         });
         });
@@ -175,7 +174,7 @@ const EnvGroupModal: React.FC<Props> = ({
       <ColumnContainer>
       <ColumnContainer>
 
 
         <ScrollableContainer>
         <ScrollableContainer>
-          {syncedEnvGroups.length != envGroups.length ? (<>
+          {syncedEnvGroups?.length != envGroups?.length ? (<>
             <Text color="helper">
             <Text color="helper">
               Select an Env Group to load into your application.
               Select an Env Group to load into your application.
             </Text>
             </Text>

+ 124 - 0
dashboard/src/main/home/project-settings/Metadata.tsx

@@ -0,0 +1,124 @@
+import React, { useContext, useEffect, useState } from "react";
+import styled from "styled-components";
+
+import github from "assets/github.png";
+
+import { Context } from "../../../shared/Context";
+import api from "../../../shared/api";
+import Loading from "../../../components/Loading";
+import Heading from "components/form-components/Heading";
+import Helper from "components/form-components/Helper";
+
+import TabSelector from "components/TabSelector";
+import Link from "components/porter/Link";
+import Spacer from "components/porter/Spacer";
+import Text from "components/porter/Text";
+import CopyToClipboard from "components/CopyToClipboard";
+import copy from "assets/copy-left.svg"
+import Icon from "components/porter/Icon";
+import { ClusterType } from "shared/types";
+
+type Props = {
+};
+
+const Metadata: React.FC<Props> = ({
+}) => {
+    const [isExpanded, setIsExpanded] = useState(false);
+    const { currentProject } = useContext(Context);
+    const [clusters, setClusters] = useState<ClusterType[]>([]);
+    const [registries, setRegistries] = useState<any[]>(null);
+    // Add name as a property of the component
+    const IdTextWithCopy = ({ id, name }: { id: number, name: string }) => (
+        <IdContainer>
+            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
+                <span style={{ fontSize: '0.8em', marginRight: '10px' }}> {name}</span>
+                <div style={{ display: 'flex', alignItems: 'center' }}>
+                    <span style={{ fontSize: '0.8em', marginRight: '5px' }}>Id: {id}</span>
+                    <CopyToClipboard text={id.toString()}>
+                        <img src={copy} alt="copy" style={{ cursor: "pointer", marginLeft: "5px", marginRight: "5px", width: "10px", height: "10px" }} />
+                    </CopyToClipboard>
+                </div>
+            </div>
+        </IdContainer>
+    );
+
+
+    useEffect(() => {
+        if (currentProject) {
+            const project_id = currentProject.id;
+
+            api
+                .getProjectRegistries("<token>", {}, { id: project_id })
+                .then((res: any) => {
+                    setRegistries(res.data);
+                })
+                .catch((err: any) => console.log(err));
+
+            api
+                .getClusters("<token>", {}, { id: currentProject?.id })
+                .then((res) => {
+                    if (res.data) {
+                        let clusters = res.data;
+                        clusters.sort((a: any, b: any) => a.id - b.id);
+                        if (clusters.length > 0) {
+                            let options = clusters.map((item: { name: any; vanity_name: string; }) => ({
+                                label: (item.vanity_name ? item.vanity_name : item.name),
+                                value: item.name
+                            }));
+                            setClusters(clusters);
+                        }
+                    }
+                });
+        }
+    }, [currentProject]);
+
+    return (
+        <>
+            <Text>Project Id: </Text>
+            <IdTextWithCopy id={currentProject?.id} name={currentProject?.name} /> {/* Assuming currentProject has name field */}
+            <Spacer y={1} />
+            {clusters?.length > 0 && <>
+                <Text>Cluster Ids:</Text>
+                {clusters?.length > 0 &&
+                    clusters.map((cluster, index) =>
+                        <IdTextWithCopy key={index} id={cluster.id} name={cluster.name} />
+                    )
+                }
+            </>
+            }
+            <Spacer y={1} />
+
+            {registries?.length > 0 &&
+                <>
+                    <Text>Registry Ids:</Text>
+                    {registries?.length > 0 &&
+                        registries.map((registry, index) =>
+                            <IdTextWithCopy key={index} id={registry.id} name={registry.name} />
+                        )
+                    }
+                </>}
+
+        </>
+    );
+};
+
+export default Metadata;
+
+const IdContainer = styled.div`
+    color: #aaaabb;
+    border-radius: 5px;
+    padding: 5px;
+    display: block;
+    width: 100%;
+    border-radius: 5px;
+    border: 1px solid ${({ theme }) => theme.border};
+    margin-bottom: 10px;
+    margin-top: 5px;
+`;
+
+// const BoxContainer = styled.div`
+// color: #aaaabb;
+// border-radius: 5px;
+// background: ${({ theme }) => theme.fg}};
+// border: 1px solid ${({ theme }) => theme.border};
+// `;

+ 5 - 2
dashboard/src/main/home/project-settings/ProjectSettings.tsx

@@ -17,6 +17,7 @@ import _ from "lodash";
 import Link from "components/porter/Link";
 import Link from "components/porter/Link";
 import Spacer from "components/porter/Spacer";
 import Spacer from "components/porter/Spacer";
 import ProjectDeleteConsent from "./ProjectDeleteConsent";
 import ProjectDeleteConsent from "./ProjectDeleteConsent";
+import Metadata from "./Metadata";
 
 
 type PropsType = RouteComponentProps & WithAuthProps & {};
 type PropsType = RouteComponentProps & WithAuthProps & {};
 
 
@@ -74,7 +75,6 @@ class ProjectSettings extends Component<PropsType, StateType> {
     if (this.state.projectName !== currentProject.name) {
     if (this.state.projectName !== currentProject.name) {
       this.setState({ projectName: currentProject.name });
       this.setState({ projectName: currentProject.name });
     }
     }
-
     const tabOptions = [];
     const tabOptions = [];
     tabOptions.push({ value: "manage-access", label: "Manage access" });
     tabOptions.push({ value: "manage-access", label: "Manage access" });
     // ? Disabled for now https://discord.com/channels/542888846271184896/1059277393031856208/1059277395913351258
     // ? Disabled for now https://discord.com/channels/542888846271184896/1059277393031856208/1059277395913351258
@@ -82,7 +82,7 @@ class ProjectSettings extends Component<PropsType, StateType> {
     //   value: "billing",
     //   value: "billing",
     //   label: "Billing",
     //   label: "Billing",
     // });
     // });
-
+    tabOptions.push({ value: "metadata", label: "Metadata" });
     if (this.props.isAuthorized("settings", "", ["get", "delete"])) {
     if (this.props.isAuthorized("settings", "", ["get", "delete"])) {
       // if (this.context?.hasBillingEnabled) {
       // if (this.context?.hasBillingEnabled) {
       //   tabOptions.push({
       //   tabOptions.push({
@@ -128,6 +128,9 @@ class ProjectSettings extends Component<PropsType, StateType> {
 
 
     if (this.state.currentTab === "manage-access") {
     if (this.state.currentTab === "manage-access") {
       return <InvitePage />;
       return <InvitePage />;
+    }
+    else if (this.state.currentTab == "metadata") {
+      return <Metadata />
     } else if (this.state.currentTab === "api-tokens") {
     } else if (this.state.currentTab === "api-tokens") {
       return <APITokensSection />;
       return <APITokensSection />;
     } else if (this.state.currentTab === "billing") {
     } else if (this.state.currentTab === "billing") {