Justin Rhee 3 лет назад
Родитель
Сommit
313568b394

+ 69 - 53
dashboard/src/main/home/new-project/NewProject.tsx

@@ -15,6 +15,7 @@ import { isAlphanumeric } from "shared/common";
 import InputRow from "components/form-components/InputRow";
 import Helper from "components/form-components/Helper";
 import TitleSection from "components/TitleSection";
+import WelcomeForm from "./WelcomeForm";
 import { trackCreateNewProject } from "shared/anayltics";
 
 type ValidationError = {
@@ -23,13 +24,12 @@ type ValidationError = {
 };
 
 export const NewProjectFC = () => {
-  const { user, setProjects, setCurrentProject, canCreateProject } = useContext(
+  const { user, setProjects, setCurrentProject, canCreateProject, projects, capabilities } = useContext(
     Context
   );
   const { pushFiltered } = useRouting();
   const [buttonStatus, setButtonStatus] = useState("");
   const [name, setName] = useState("");
-  const { projects } = useContext(Context);
 
   useEffect(() => {
     if (!canCreateProject) {
@@ -103,61 +103,77 @@ export const NewProjectFC = () => {
     }
   };
 
+  const renderContents = () => {
+    let version = capabilities?.version;
+    alert(user.email)
+    if (version !== "production" || user.email === "support@porter.run") {
+      return (
+        <>
+          <FadeWrapper>
+            {!isFirstProject && (
+              <BackButton
+                onClick={() => {
+                  pushFiltered("/dashboard", []);
+                }}
+              >
+                <BackButtonImg src={backArrow} />
+              </BackButton>
+            )}
+            <TitleSection>New project</TitleSection>
+          </FadeWrapper>
+          <FadeWrapper delay="0.7s">
+            <Helper>
+              Project name
+              <Warning highlight={validateProjectName().hasError}>
+                (lowercase letters, numbers, and "-" only)
+              </Warning>
+              <Required>*</Required>
+            </Helper>
+          </FadeWrapper>
+          <SlideWrapper delay="1.2s">
+            <InputWrapper>
+              <ProjectIcon>
+                <ProjectImage src={gradient} />
+                <Letter>{name ? name.toUpperCase().substring(0, 1) : "-"}</Letter>
+              </ProjectIcon>
+              <InputRow
+                type="string"
+                value={name}
+                setValue={(x: string) => {
+                  setButtonStatus("");
+                  setName(x);
+                }}
+                placeholder="ex: perspective-vortex"
+                width="470px"
+                disabled={buttonStatus === "loading"}
+              />
+            </InputWrapper>
+            <NewProjectSaveButton
+              text="Create project"
+              disabled={false}
+              onClick={createProject}
+              status={buttonStatus}
+              makeFlush={true}
+              clearPosition={true}
+              statusPosition="right"
+              saveText="Creating project..."
+              successText="Project created successfully!"
+            />
+          </SlideWrapper>
+        </>
+      )
+    } else {
+      return (
+        <WelcomeForm />
+      )
+    }
+  }
+
   return (
     <Wrapper>
       <StyledNewProject>
         <PageIllustration />
-        <FadeWrapper>
-          {!isFirstProject && (
-            <BackButton
-              onClick={() => {
-                pushFiltered("/dashboard", []);
-              }}
-            >
-              <BackButtonImg src={backArrow} />
-            </BackButton>
-          )}
-          <TitleSection>New project</TitleSection>
-        </FadeWrapper>
-        <FadeWrapper delay="0.7s">
-          <Helper>
-            Project name
-            <Warning highlight={validateProjectName().hasError}>
-              (lowercase letters, numbers, and "-" only)
-            </Warning>
-            <Required>*</Required>
-          </Helper>
-        </FadeWrapper>
-        <SlideWrapper delay="1.2s">
-          <InputWrapper>
-            <ProjectIcon>
-              <ProjectImage src={gradient} />
-              <Letter>{name ? name.toUpperCase().substring(0, 1) : "-"}</Letter>
-            </ProjectIcon>
-            <InputRow
-              type="string"
-              value={name}
-              setValue={(x: string) => {
-                setButtonStatus("");
-                setName(x);
-              }}
-              placeholder="ex: perspective-vortex"
-              width="470px"
-              disabled={buttonStatus === "loading"}
-            />
-          </InputWrapper>
-          <NewProjectSaveButton
-            text="Create project"
-            disabled={false}
-            onClick={createProject}
-            status={buttonStatus}
-            makeFlush={true}
-            clearPosition={true}
-            statusPosition="right"
-            saveText="Creating project..."
-            successText="Project created successfully!"
-          />
-        </SlideWrapper>
+        {renderContents()}
       </StyledNewProject>
     </Wrapper>
   );

+ 290 - 0
dashboard/src/main/home/new-project/WelcomeForm.tsx

@@ -0,0 +1,290 @@
+import React, { useState } from "react";
+import axios from "axios";
+import styled from "styled-components";
+import { CSSTransition } from "react-transition-group";
+
+const WelcomeForm = (props: any) => {
+  const queryParams = new URLSearchParams(window.location.search);
+  const initEmail = queryParams.get("email");
+  const [active, setActive] = useState(true);
+  const [company, setCompany] = useState("");
+  const [companySite, setCompanySite] = useState("");
+  const [email, setEmail] = useState(initEmail || "");
+  const [isDone, setIsDone] = useState(false);
+
+  const encode = (data: any) => {
+    return Object.keys(data)
+        .map(key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
+        .join("&");
+  }
+
+  const submitForm = (e: any) => {
+    fetch("/", {
+      method: "POST",
+      headers: { "Content-Type": "application/x-www-form-urlencoded" },
+      body: encode({ "form-name": "demo", email, company, "website": companySite})
+    })
+      .then(() => {
+        setIsDone(true)
+        axios.post(
+          'https://discord.com/api/webhooks/895799932764700672/n4MBkfs20HSa10Wm1VBUXbxonJNxzKNd50LlzVQ_YHShJnnjpz-10HPP712jaWzW-oqk', 
+          {
+            username: "Demo Request",
+            content: `**${email}** from **${company}** (website: ${companySite})`
+          },
+          {
+            headers: {
+              'Content-Type': 'application/json'
+            }
+          }
+        )
+
+        axios.get('https://hooks.zapier.com/hooks/catch/8214896/o7j0q85/', {
+          params: {
+            email,
+            isCompany: true,
+            company: `${company} - ${companySite}`,
+            role: "**Requesting Demo**",
+          }
+        })
+      })
+      .catch(error => alert(error));
+
+    e.preventDefault();
+  };
+
+  return (
+    <CSSTransition
+      in={active}
+      timeout={500}
+      classNames="alert"
+      unmountOnExit
+      onEnter={() => setActive(true)}
+      onExited={() => setActive(false)}
+    >
+      <StyledWelcomeForm>
+        {
+          isDone ? (
+            <div>
+              <Title>Your response has been recorded.</Title>
+              <Subtitle>We'll be in touch shortly!</Subtitle>
+            </div>
+          ) : (
+            <form name="demo" onSubmit={submitForm}>
+              <Title>Book a Demo</Title>
+              <Subtitle>Just two things and we'll be in touch.</Subtitle>
+              <SubtitleAlt>
+                <Num>1</Num> What is your work email? *
+              </SubtitleAlt>
+              <Input
+                type="email"
+                placeholder="ex: sophon@acme.com"
+                value={email}
+                onChange={(e) => setEmail(e.target.value)}
+              />
+              <SubtitleAlt>
+                <Num>2</Num> What is your company name? *
+              </SubtitleAlt>
+              <Input
+                type="text"
+                placeholder="ex: Acme"
+                value={company}
+                onChange={(e) => setCompany(e.target.value)}
+              />
+              <SubtitleAlt>
+                <Num>3</Num> What is your company website? *
+              </SubtitleAlt>
+              <Input
+                type="text"
+                name="website"
+                placeholder="ex: https://acme.com"
+                value={companySite}
+                onChange={(e) => setCompanySite(e.target.value)}
+              />
+              <Submit
+                type="submit"
+                value="Done"
+                disabled={!company || !email || !companySite}
+              />
+            </form>
+          )
+        }
+      </StyledWelcomeForm>
+    </CSSTransition>
+  );
+};
+
+export default WelcomeForm;
+
+const Hamburger = styled.div`
+  width: 45px;
+  margin-right: -5px;
+  position: fixed;
+  cursor: pointer;
+  top: 30px;
+  right: 30px;
+  z-index: 999;
+  height: 45px;
+  border-radius: 100px;
+  border: 2px solid #aaaabb;
+  background: #ffffff33;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  :hover {
+    background: #ffffff44;
+    width: 45px;
+    height: 45px;
+  }
+`;
+
+const Num = styled.div`
+  display: flex;
+  align-items: center;
+  margin-right: 15px;
+  justify-content: center;
+  width: 30px;
+  height: 30px;
+  border: 1px solid #ffffff;
+`;
+
+const Option = styled.input`
+  width: 500px;
+  max-width: 80vw;
+  height: 50px;
+  background: #ffffff22;
+  display: flex;
+  align-items: center;
+  margin-top: 15px;
+  color: #ffffff;
+  border: 1px solid #aaaabb;
+  border-radius: 5px;
+  padding-left: 15px;
+  cursor: pointer;
+  :hover {
+    background: #ffffff44;
+  }
+
+  > i {
+    font-size: 20px;
+    margin-right: 12px;
+    color: #aaaabb;
+  }
+
+  opacity: 0;
+  animation: slideIn 0.7s 1.3s;
+  animation-fill-mode: forwards;
+
+  @keyframes slideIn {
+    from {
+      opacity: 0;
+      transform: translateX(-30px);
+    }
+    to {
+      opacity: 1;
+      transform: translateX(0);
+    }
+  }
+`;
+
+const Submit = styled(Option)`
+  border: 0;
+  opacity: 0;
+  user-select: none;
+  animation: fadeIn 0.7s 0.3s;
+  animation-fill-mode: forwards;
+  margin-top: 35px;
+  cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
+  background: ${(props) => (props.disabled ? "#aaaabb" : "#616FEEcc")};
+  :hover {
+    filter: ${(props) => (props.disabled ? "" : "brightness(130%)")};
+    background: ${(props) => (props.disabled ? "#aaaabb" : "#616FEEcc")};
+  }
+
+  > i {
+    color: #ffffff;
+  }
+`;
+
+const Input = styled.input`
+  width: 500px;
+  max-width: 80vw;
+  height: 50px;
+  background: #ffffff22;
+  font-size: 18px;
+  display: flex;
+  align-items: center;
+  margin-top: 0px;
+  color: #ffffff;
+  border: 1px solid #aaaabb;
+  border-radius: 5px;
+  padding-left: 15px;
+  margin-bottom: 40px;
+
+  opacity: 0;
+  animation: fadeIn 0.5s 0.2s;
+  animation-fill-mode: forwards;
+`;
+
+const Subtitle = styled.div`
+  margin: 20px 0 30px;
+  color: #aaaabb;
+
+  opacity: 0;
+  animation: fadeIn 0.5s 0.2s;
+  animation-fill-mode: forwards;
+`;
+
+const SubtitleAlt = styled(Subtitle)`
+  margin: -5px 0 30px;
+  color: white;
+  display: flex;
+  align-items: center;
+  animation: fadeIn 0.5s 0.2s;
+  animation-fill-mode: forwards;
+`;
+
+const Title = styled.div`
+  color: white;
+  margin-top: -10px;
+
+  font-size: 26px;
+  margin-bottom: 5px;
+  display: flex;
+  align-items: center;
+
+  opacity: 0;
+  animation: fadeIn 0.5s 0.2s;
+  animation-fill-mode: forwards;
+
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 1;
+    }
+  }
+`;
+
+const StyledWelcomeForm = styled.div`
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  font-family: "Work Sans", sans-serif;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  &.alert-exit {
+    opacity: 1;
+  }
+  &.alert-exit-active {
+    opacity: 0;
+    transform: translateY(-100px);
+    transition: opacity 500ms, transform 1000ms;
+  }
+`;

+ 1 - 0
dashboard/src/shared/types.tsx

@@ -320,6 +320,7 @@ export type FullActionConfigType = ActionConfigType & {
 export interface CapabilityType {
   github: boolean;
   provisioner: boolean;
+  version?: string;
 }
 
 export interface ContextProps {