From 20d8d255cbb23ef1355b2ee5b66ad420ca9d5c3f Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Sat, 3 Dec 2022 23:23:32 -0500 Subject: [PATCH] Added a quick start guide for new users --- frontend/components/basic/layout.js | 135 ++++++++++-------- frontend/components/billing/Plan.js | 2 +- .../pages/api/organization/GetOrgUsers.js | 8 +- frontend/pages/home/[id].tsx | 135 ++++++++++++++++++ frontend/pages/signup.js | 4 +- 5 files changed, 222 insertions(+), 62 deletions(-) create mode 100644 frontend/pages/home/[id].tsx diff --git a/frontend/components/basic/layout.js b/frontend/components/basic/layout.js index 0a8cb3ebd..63dbf5dea 100644 --- a/frontend/components/basic/layout.js +++ b/frontend/components/basic/layout.js @@ -3,8 +3,9 @@ import { useEffect, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/router"; import { + faBookOpen, faGear, - faHouse, + faKey, faMobile, faPlug, faUser, @@ -114,7 +115,7 @@ export default function Layout({ children }) { href: "/dashboard/" + workspaceMapping[workspaceSelected] + "?Development", title: "Secrets", - emoji: , + emoji: , }, { href: "/users/" + workspaceMapping[workspaceSelected], @@ -214,66 +215,88 @@ export default function Layout({ children }) {
)} - +
{plan.buttonTextSecondary}
diff --git a/frontend/pages/api/organization/GetOrgUsers.js b/frontend/pages/api/organization/GetOrgUsers.js index feeb60477..81e9caa4d 100644 --- a/frontend/pages/api/organization/GetOrgUsers.js +++ b/frontend/pages/api/organization/GetOrgUsers.js @@ -2,13 +2,13 @@ import SecurityClient from "~/utilities/SecurityClient"; /** * This route lets us get all the users in an org. - * @param {*} req - * @param {*} res + * @param {object} obj + * @param {string} obj.orgId - organization Id * @returns */ -const getOrganizationUsers = (req, res) => { +const getOrganizationUsers = ({ orgId }) => { return SecurityClient.fetchCall( - "/api/v1/organization/" + req.orgId + "/users", + "/api/v1/organization/" + orgId + "/users", { method: "GET", headers: { diff --git a/frontend/pages/home/[id].tsx b/frontend/pages/home/[id].tsx new file mode 100644 index 000000000..25cd87ad3 --- /dev/null +++ b/frontend/pages/home/[id].tsx @@ -0,0 +1,135 @@ +import React, { useEffect, useState } from "react"; +import Link from "next/link"; +import { useRouter } from "next/router"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import { faSlack } from "@fortawesome/free-brands-svg-icons"; +import { faCheckCircle, faHandPeace, faNetworkWired, faPlug, faPlus, faUserPlus } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import getOrganizationUsers from "../api/organization/GetOrgUsers"; +import checkUserAction from "../api/userActions/checkUserAction"; +import registerUserAction from "../api/userActions/registerUserAction"; + +type ItemProps = { + text: string; + subText: string; + complete: boolean; + icon: IconProp; + time: string; + userAction?: string; + link?: string; +}; + +const learningItem = ({ text, subText, complete, icon, time, userAction, link }: ItemProps): JSX.Element => { + if (link) { + return ( + +
+
{ + if (userAction) { + await registerUserAction({ + action: userAction + }) + } + }} + className="relative bg-bunker-700 hover:bg-bunker-500 shadow-xl duration-200 rounded-md border border-dashed border-bunker-400 pl-2 pr-6 py-2 h-[5.5rem] w-full flex items-center justify-between overflow-hidden my-1.5 cursor-pointer"> +
+ + {complete && +
+ +
} +
+
{text}
+
{subText}
+
+
+
+ {complete ? "Complete!" : "About " + time} +
+ {complete &&
} +
+
+ + ); + } else { + return ( +
{ + if (userAction) { + await registerUserAction({ + action: userAction + }) + } + }} + className="relative bg-bunker-700 hover:bg-bunker-500 shadow-xl duration-200 rounded-md border border-dashed border-bunker-400 pl-2 pr-6 py-2 h-[5.5rem] w-full flex items-center justify-between overflow-hidden my-1.5 cursor-pointer"> +
+ + {complete && +
+ +
} +
+
{text}
+
{subText}
+
+
+
+ {complete ? "Complete!" : "About " + time} +
+ {complete &&
} +
+ ); + } +} + +/** + * This tab is called Home because in the future it will include some company news, + * updates, roadmap, relavant blogs, etc. Currently it only has the setup instruction + * for the new users + */ +export default function Home() { + const router = useRouter(); + const [hasUserClickedSlack, setHasUserClickedSlack] = useState(false); + const [hasUserClickedIntro, setHasUserClickedIntro] = useState(false); + const [usersInOrg, setUsersInOrg] = useState(false); + + useEffect(() => { + const checkUserActionsFunction = async () => { + let userActionSlack = await checkUserAction({ + action: "slack_cta_clicked", + }); + setHasUserClickedSlack(userActionSlack ? true : false); + + let userActionIntro = await checkUserAction({ + action: "intro_cta_clicked", + }); + setHasUserClickedIntro(userActionIntro ? true : false); + + let orgId = localStorage.getItem("orgData.id"); + const orgUsers = await getOrganizationUsers({ + orgId: orgId ? orgId : "", + }); + setUsersInOrg(orgUsers.length > 1) + }; + checkUserActionsFunction(); + }, []); + + return ( +
+
+
Your quick start guide
+
Click on the items below and follow the instructions.
+ {learningItem({ text: "Get to know Infisical", subText: "", complete: hasUserClickedIntro, icon: faHandPeace, time: "3 min", userAction: "intro_cta_clicked", link: "https://www.youtube.com/watch?v=JS3OKYU2078" })} + {learningItem({ text: "Add your secrets", subText: "Click to see example secrets, and add your own.", complete: false, icon: faPlus, time: "2 min", userAction: "first_time_secrets_pushed", link: "/dashboard/" + router.query.id })} + {learningItem({ text: "Inject secrets locally", subText: "Replace .env files with a more secure an efficient alternative.", complete: false, icon: faNetworkWired, time: "12 min", link: "https://infisical.com/docs/getting-started/quickstart" })} + {learningItem({ text: "Integrate Infisical with your infrastructure", subText: "Only a few integrations are currently available. Many more coming soon!", complete: false, icon: faPlug, time: "15 min", link: "https://infisical.com/docs/integrations/overview" })} + {learningItem({ text: "Invite your teammates", subText: "", complete: usersInOrg, icon: faUserPlus, time: "2 min", link: "/settings/org/" + router.query.id + "?invite" })} + {learningItem({ text: "Join Infisical Slack", subText: "Have any questions? Ask us!", complete: hasUserClickedSlack, icon: faSlack, time: "1 min", userAction: "slack_cta_clicked", link: "https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g" })} +
+
+ ); +} + +Home.requireAuth = true; diff --git a/frontend/pages/signup.js b/frontend/pages/signup.js index 14ae51dcf..dfd497cd7 100644 --- a/frontend/pages/signup.js +++ b/frontend/pages/signup.js @@ -495,7 +495,9 @@ export default function SignUp() { setBackupKeyError, setBackupKeyIssued, }); - router.push("/dashboard/"); + const userWorkspaces = await getWorkspaces(); + let userWorkspace = userWorkspaces[0]._id; + router.push("/home/" + userWorkspace); }} size="lg" />