Stefan McShane 3 лет назад
Родитель
Сommit
eb9261382c

+ 2 - 2
.gitignore

@@ -21,8 +21,8 @@ openapi.yaml
 vendor
 **/*.env
 **/node_modules
-porter
-migrate
+migrate-binary
+porter-binary
 zarf/helm/charts
 
 # Local docs directories

+ 2 - 2
Tiltfile

@@ -15,7 +15,7 @@ if config.tilt_subcommand == "down":
 ## Build binary locally for faster devexp
 local_resource(
   name='porter-binary',
-  cmd='''GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod vendor -gcflags '-N -l' -tags ee -o ./porter ./cmd/app/main.go''',
+  cmd='''GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod vendor -gcflags '-N -l' -tags ee -o ./porter-binary ./cmd/app/main.go''',
   deps=[
     "api",
     "build",
@@ -63,7 +63,7 @@ local_resource(
 # Migrations
 local_resource(
     name="migrations-binary",
-    cmd='''GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod vendor -gcflags '-N -l' -tags ee -o ./migrate ./cmd/migrate/main.go ./cmd/migrate/migrate_ee.go''',
+    cmd='''GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -mod vendor -gcflags '-N -l' -tags ee -o ./migrate-binary ./cmd/migrate/main.go ./cmd/migrate/migrate_ee.go''',
     resource_deps=["postgresql"],
     labels=["porter"],
 )

+ 12 - 12
dashboard/src/components/ProvisionerFlow.tsx

@@ -14,6 +14,7 @@ import Fieldset from "./porter/Fieldset";
 import Checkbox from "./porter/Checkbox";
 import Button from "./porter/Button";
 import ExpandableSection from "./porter/ExpandableSection";
+import Input from "./porter/Input";
 
 const providers = ["aws", "gcp", "azure"];
 
@@ -26,7 +27,7 @@ const ProvisionerFlow: React.FC<Props> = ({
   const [currentStep, setCurrentStep] = useState("cloud");
   const [credentialId, setCredentialId] = useState("");
   const [showCostConfirmModal, setShowCostConfirmModal] = useState(false);
-  const [costConfirmed, setCostConfirmed] = useState(false);
+  const [confirmCost, setConfirmCost] = useState("");
 
   const isUsageExceeded = useMemo(() => {
     if (!hasBillingEnabled) {
@@ -65,11 +66,11 @@ const ProvisionerFlow: React.FC<Props> = ({
         </StyledProvisionerFlow>
         {showCostConfirmModal && (
           <Modal closeModal={() => {
-            setCostConfirmed(false);
+            setConfirmCost("");
             setShowCostConfirmModal(false);
           }}>
             <Text size={16} weight={500}>
-              Important: AWS base cost
+              AWS base cost consent
             </Text>
             <Spacer height="15px" />
             <Text color="helper">
@@ -103,21 +104,20 @@ const ProvisionerFlow: React.FC<Props> = ({
             />
             <Spacer y={1} />
             <Text color="helper">
-              All AWS resources will be automatically deleted when you delete your Porter project.
+              Porter metered cost: $0.019/hr/vCPU + $0.009/hr/GB RAM.
             </Text>
             <Spacer y={1} />
-            <Checkbox 
-              checked={costConfirmed} 
-              toggleChecked={() => setCostConfirmed(!costConfirmed)}
-            >
-              I understand and wish to proceed.
-            </Checkbox>
+            <Text color="helper">
+              All AWS resources will be automatically deleted when you delete your Porter project. Please enter the base cost ("315.94") below to proceed:
+            </Text>
+            <Spacer y={1} />
+            <Input placeholder="315.94" value={confirmCost} setValue={setConfirmCost} width="100%" height="40px" />
             <Spacer y={1} />
             <Button
-              disabled={!costConfirmed}
+              disabled={confirmCost !== "315.94"}
               onClick={() => {
                 setShowCostConfirmModal(false);
-                setCostConfirmed(false);
+                setConfirmCost("");
                 setCurrentStep("credentials");
               }}
             >

+ 52 - 0
dashboard/src/components/porter/Checkbox.tsx

@@ -0,0 +1,52 @@
+import React, { useEffect, useState } from "react";
+import styled from "styled-components";
+
+type Props = {
+  checked: boolean;
+  toggleChecked: () => void;
+  children: React.ReactNode;
+};
+
+const Checkbox: React.FC<Props> = ({
+  checked,
+  toggleChecked,
+  children,
+}) => {
+  return (
+    <StyledCheckbox>
+      <Box 
+        checked={checked}
+        onClick={toggleChecked}
+      >
+        <i className="material-icons">done</i>
+      </Box>
+      {children}
+    </StyledCheckbox>
+  );
+};
+
+export default Checkbox;
+
+const StyledCheckbox = styled.div`
+  display: flex;
+  align-items: center;
+`;
+
+const Box = styled.div<{ checked: boolean }>`
+  width: 12px;
+  height: 12px;
+  cursor: pointer;
+  border: 1px solid #ffffff55;
+  margin-right: 10px;
+  border-radius: 3px;
+  background: ${(props) => (props.checked ? "#ffffff22" : "#ffffff11")};
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  > i {
+    font-size: 12px;
+    padding-left: 0px;
+    display: ${(props) => (props.checked ? "" : "none")};
+  }
+`;

+ 39 - 0
dashboard/src/components/porter/Fieldset.tsx

@@ -0,0 +1,39 @@
+import React, { useEffect, useState } from "react";
+import styled from "styled-components";
+
+type Props = {
+  children: React.ReactNode;
+  background?: string;
+};
+
+const Fieldset: React.FC<Props> = ({
+  children,
+  background,
+}) => {
+  const getBackground = () => {
+    switch (background) {
+      case "dark":
+        return "#1b1d2688";
+      default:
+        return background;
+    }
+  };
+  return (
+    <StyledFieldset background={getBackground()}>
+      {children}
+    </StyledFieldset>
+  );
+};
+
+export default Fieldset;
+
+const StyledFieldset = styled.div<{
+  background?: string;
+}>`
+  position: relative;
+  padding: 25px;
+  border-radius: 5px;
+  background: ${props => props.background || "#26292e"};
+  border: 1px solid #494b4f;
+  font-size: 13px;
+`;

+ 99 - 0
dashboard/src/components/porter/Modal.tsx

@@ -0,0 +1,99 @@
+import React, { useEffect, useState } from "react";
+import styled from "styled-components";
+
+type Props = {
+  closeModal?: () => void;
+  children: React.ReactNode;
+};
+
+const Modal: React.FC<Props> = ({
+  closeModal,
+  children,
+}) => {
+  return (
+    <ModalWrapper>
+      <ModalBg onClick={closeModal} />
+      <StyledModal> 
+        {closeModal && (
+          <CloseButton onClick={closeModal}>
+            <i className="material-icons">close</i>
+          </CloseButton>
+        )}
+        {children}
+      </StyledModal>
+    </ModalWrapper>
+  );
+};
+
+export default Modal;
+
+const CloseButton = styled.div`
+  position: absolute;
+  display: block;
+  width: 40px;
+  height: 40px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1;
+  border-radius: 50%;
+  right: 12px;
+  top: 10px;
+  cursor: pointer;
+  :hover {
+    background-color: #ffffff11;
+  }
+
+  > i {
+    font-size: 20px;
+    color: #aaaabb;
+  }
+`;
+
+const ModalWrapper = styled.div`
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: fixed;
+  margin: 0;
+  padding: 0;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  height: 100vh;
+  z-index: 100;
+`;
+
+const ModalBg = styled.div`
+  position: fixed;
+  margin: 0;
+  padding: 0;
+  top: 0;
+  left: 0;
+  width: 100vw;
+  height: 100vh;
+  background-color: rgba(0, 0, 0, 0.6);
+`;
+
+const StyledModal = styled.div`
+  position: relative;
+  padding: 25px;
+  border-radius: 10px;
+  border: 1px solid #494b4f;
+  font-size: 13px;
+  width: 600px;
+  background: #42444944;
+  backdrop-filter: saturate(150%) blur(10px);
+
+  animation: floatInModal 0.5s 0s;
+  @keyframes floatInModal {
+    from {
+      opacity: 0;
+      transform: translateY(30px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0px);
+    }
+  }
+`;