first draft new sidebar

This commit is contained in:
Vladyslav Matsiiako
2023-06-28 14:28:52 -07:00
parent 68c8dad829
commit dfc88d99f6
5 changed files with 535 additions and 90 deletions

View File

@ -48,7 +48,7 @@ export const MenuItem = <T extends ElementType = "button">({
>
<li
className={twMerge(
"group px-1 py-2.5 mt-0.5 font-inter flex flex-col text-sm text-bunker-100 transition-all rounded cursor-pointer hover:bg-mineshaft-700 duration-50",
"group px-1 py-2 mt-0.5 font-inter flex flex-col text-sm text-bunker-100 transition-all rounded cursor-pointer hover:bg-mineshaft-700 duration-50",
isSelected && "bg-mineshaft-600 hover:bg-mineshaft-600",
isDisabled && "hover:bg-transparent cursor-not-allowed",
className
@ -56,16 +56,16 @@ export const MenuItem = <T extends ElementType = "button">({
>
<motion.span className="w-full flex flex-row items-center justify-start rounded-sm">
<Item type="button" role="menuitem" className="flex items-center relative" ref={inputRef} {...props}>
<div className={`${isSelected ? "visisble" : "invisible"} absolute w-[0.25rem] rounded-md h-8 bg-primary`}/>
<div className={`${isSelected ? "visisble" : "invisible"} absolute w-[0.2rem] rounded-md h-7 bg-primary`}/>
{/* {icon && <span className="mr-3 ml-4 w-5 block group-hover:hidden">{icon}</span>} */}
<Lottie
lottieRef={iconRef}
style={{ width: 24, height: 24 }}
style={{ width: 22, height: 22 }}
// eslint-disable-next-line import/no-dynamic-require
animationData={require(`../../../../public/lotties/${icon}.json`)}
loop={false}
autoplay={false}
className="my-auto ml-3 mr-3"
className="my-auto ml-[0.1rem] mr-3"
/>
<span className="flex-grow text-left">{children}</span>
</Item>

View File

@ -72,12 +72,12 @@ export const TabsObject = () => {
>
Windows
</Tabs.Trigger>
<Tabs.Trigger
{/* <Tabs.Trigger
className="bg-bunker-700 px-5 h-10 flex-1 flex items-center justify-center text-sm leading-none text-bunker-300 select-none first:rounded-tl-md last:rounded-tr-md data-[state=active]:text-primary data-[state=active]:font-medium data-[state=active]:focus:relative data-[state=active]:border-b data-[state=active]:border-primary outline-none cursor-default"
value="tab3"
>
Arch Linux
</Tabs.Trigger>
</Tabs.Trigger> */}
<a
target='_blank'
rel="noopener noreferrer"
@ -88,7 +88,7 @@ export const TabsObject = () => {
</a>
</Tabs.List>
<Tabs.Content
className="grow p-5 bg-bunker-700 rounded-b-md outline-none cursor-default"
className="grow p-5 pt-0 bg-bunker-700 rounded-b-md outline-none cursor-default"
value="tab1"
>
<CodeItem isCopied={downloadCodeCopied} setIsCopied={setDownloadCodeCopied} textExplanation="1. Download CLI" code="brew install infisical/get-cli/infisical" id="downloadCode" />
@ -105,10 +105,10 @@ export const TabsObject = () => {
</a>. </p>
</Tabs.Content>
<Tabs.Content
className="grow p-5 bg-bunker-700 rounded-b-md outline-none"
className="grow p-5 pt-0 bg-bunker-700 rounded-b-md outline-none"
value="tab2"
>
<CodeItem isCopied={downloadCodeCopied} setIsCopied={setDownloadCodeCopied} textExplanation="1. Download CLI" code="brew install infisical/get-cli/infisical" id="downloadCodeW" />
<CodeItem isCopied={downloadCodeCopied} setIsCopied={setDownloadCodeCopied} textExplanation="1. Download CLI" code="scoop bucket add org https://github.com/Infisical/scoop-infisical.git" id="downloadCodeW" />
<div className='font-mono text-sm px-3 py-2 mt-2 bg-bunker rounded-md border border-mineshaft-600 flex flex-row items-center justify-between'>
<input disabled value="scoop install infisical" id="downloadCodeW2" className='w-full bg-transparent text-bunker-200'/>
<button
@ -138,22 +138,5 @@ export const TabsObject = () => {
here
</a>. </p>
</Tabs.Content>
<Tabs.Content
className="grow p-5 bg-bunker-700 rounded-b-md outline-none cursor-default"
value="tab3"
>
<CodeItem isCopied={downloadCodeCopied} setIsCopied={setDownloadCodeCopied} textExplanation="1. Download CLI" code="brew install infisical/get-cli/infisical" id="downloadCodeL" />
<CodeItem isCopied={loginCodeCopied} setIsCopied={setLoginCodeCopied} textExplanation="2. Login" code="infisical login" id="loginCodeL" />
<CodeItem isCopied={initCodeCopied} setIsCopied={setInitCodeCopied} textExplanation="3. Choose Project" code="infisical init" id="initCodeL" />
<CodeItem isCopied={runCodeCopied} setIsCopied={setRunCodeCopied} textExplanation="4. Done! Now, you can prepend your usual start script with:" code="infisical run -- [YOUR USUAL CODE START SCRIPT GOES HERE]" id="runCodeL" />
<p className='text-bunker-300 text-sm mt-2'>You can find example of start commands for different frameworks <a
className='text-primary underline underline-offset-2'
target="_blank"
rel="noopener noreferrer"
href='https://infisical.com/docs/integrations/overview'
>
here
</a>. </p>
</Tabs.Content>
</Tabs.Root>
};

View File

@ -12,7 +12,7 @@ import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import Link from "next/link";
import { useRouter } from "next/router";
import { faBookOpen, faMobile, faPlus } from "@fortawesome/free-solid-svg-icons";
import { faAngleDown, faBookOpen, faMobile, faPlus, faQuestion } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { yupResolver } from "@hookform/resolvers/yup";
import queryString from "query-string";
@ -257,13 +257,20 @@ export const AppLayout = ({ children }: LayoutProps) => {
return (
<>
<div className="dark hidden h-screen w-full flex-col overflow-x-hidden md:flex">
<Navbar />
{/* <Navbar /> */}
<div className="flex flex-grow flex-col overflow-y-hidden md:flex-row">
<aside className="w-full border-r border-mineshaft-600 bg-gradient-to-tr from-mineshaft-700 via-mineshaft-800 to-mineshaft-900 md:w-60">
<nav className="items-between flex h-full flex-col justify-between">
<div>
{currentWorkspace && router.asPath !== "/noprojects" ? (
<div className="mt-3 mb-4 w-full p-4">
<div className="h-12 px-3 flex items-center pt-6 cursor-default">
<div className="mr-auto flex items-center hover:bg-mineshaft-600 py-1.5 pl-1.5 pr-2 rounded-md">
<div className="w-5 h-5 rounded-md bg-[#E0ED34] flex justify-center items-center">I</div>
<div className="pl-3.5 text-mineshaft-100 text-sm">Infisical <FontAwesomeIcon icon={faAngleDown} className="text-xs pl-1 pt-1 text-mineshaft-300" /></div>
</div>
<div className="w-5 h-5 rounded-full bg-green hover:opacity-80 pr-1"></div>
</div>
{!router.asPath.includes("org") && (currentWorkspace && router.asPath !== "/noprojects" ? (
<div className="mt-3 mb-4 w-full p-3">
<p className="ml-1.5 mb-1 text-xs font-semibold uppercase text-gray-400">
Project
</p>
@ -331,9 +338,9 @@ export const AppLayout = ({ children }: LayoutProps) => {
Add Project
</Button>
</div>
)}
<div className={`${currentWorkspace && router.asPath !== "/noprojects" ? "block" : "hidden"}`}>
<Menu>
))}
<div className={`px-1 ${currentWorkspace && router.asPath !== "/noprojects" ? "block" : "hidden"}`}>
{router.asPath.includes("project") ? <Menu>
<Link href={`/dashboard/${currentWorkspace?._id}`} passHref>
<a>
<MenuItem
@ -386,53 +393,51 @@ export const AppLayout = ({ children }: LayoutProps) => {
</a>
</Link>
</Menu>
: <Menu className="mt-4">
<Link href={`/dashboard/${currentWorkspace?._id}`} passHref>
<a>
<MenuItem
isSelected={router.asPath.includes(`/dashboard/${currentWorkspace?._id}`)}
icon="system-outline-90-lock-closed"
>
Overview
</MenuItem>
</a>
</Link>
<Link href={`/users/${currentWorkspace?._id}`} passHref>
<a>
<MenuItem
isSelected={router.asPath === `/users/${currentWorkspace?._id}`}
icon="system-outline-96-groups"
>
{t("nav.menu.members")}
</MenuItem>
</a>
</Link>
<Link href={`/settings/project/${currentWorkspace?._id}`} passHref>
<a>
<MenuItem
isSelected={
router.asPath === `/settings/project/${currentWorkspace?._id}`
}
icon="system-outline-109-slider-toggle-settings"
>
Org Setting
</MenuItem>
</a>
</Link>
</Menu>}
</div>
</div>
<div className="mt-40 mb-4 w-full px-2">
{router.asPath.split("/")[1] === "home" ? (
<div className="relative flex cursor-pointer rounded bg-primary-50/10 px-0.5 py-2.5 text-sm text-white">
<div className="absolute inset-0 top-0 my-1 ml-1 mr-1 w-1 rounded-xl bg-primary" />
<p className="ml-4 mr-2 flex w-6 items-center justify-center text-lg">
<FontAwesomeIcon icon={faBookOpen} />
</p>
Infisical Guide
<img
src={`/images/progress-${totalOnboardingActionsDone === 0 ? "0" : ""}${
totalOnboardingActionsDone === 1 ? "14" : ""
}${totalOnboardingActionsDone === 2 ? "28" : ""}${
totalOnboardingActionsDone === 3 ? "43" : ""
}${totalOnboardingActionsDone === 4 ? "57" : ""}${
totalOnboardingActionsDone === 5 ? "71" : ""
}.svg`}
height={58}
width={58}
alt="progress bar"
className="absolute right-2 -top-2"
/>
</div>
) : (
<Link href={`/home/${currentWorkspace?._id}`}>
<div className="mt-max relative flex h-10 cursor-pointer overflow-visible rounded bg-white/10 p-2.5 text-sm text-white hover:bg-primary-50/[0.15]">
<p className="flex w-10 items-center justify-center text-lg">
<FontAwesomeIcon icon={faBookOpen} />
</p>
Infisical Guide
<img
src={`/images/progress-${totalOnboardingActionsDone === 0 ? "0" : ""}${
totalOnboardingActionsDone === 1 ? "14" : ""
}${totalOnboardingActionsDone === 2 ? "28" : ""}${
totalOnboardingActionsDone === 3 ? "43" : ""
}${totalOnboardingActionsDone === 4 ? "57" : ""}${
totalOnboardingActionsDone === 5 ? "71" : ""
}.svg`}
height={58}
width={58}
alt="progress bar"
className="absolute right-2 -top-2"
/>
</div>
</Link>
)}
<div className="mt-40 mb-4 w-full px-2 text-mineshaft-400 cursor-default pl-6 text-sm">
<div className="hover:text-mineshaft-200 duration-200 mb-3">
<FontAwesomeIcon icon={faPlus} className="mr-3"/>
Invite people
</div>
<div className="hover:text-mineshaft-200 duration-200 mb-2">
<FontAwesomeIcon icon={faQuestion} className="px-[0.1rem] mr-3"/>
Help & Support
</div>
</div>
</nav>
</aside>

View File

@ -0,0 +1,433 @@
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import Head from "next/head";
import Image from "next/image";
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 { faArrowRight, faCheckCircle, faHandPeace, faMagnifyingGlass, faNetworkWired, faPlug, faPlus, faStar, faUserPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import AddProjectMemberDialog from "@app/components/basic/dialog/AddProjectMemberDialog";
import ProjectUsersTable from "@app/components/basic/table/ProjectUsersTable";
import guidGenerator from "@app/components/utilities/randomId";
import { useWorkspace } from "@app/context";
import { Workspace } from "@app/hooks/api/workspace/types";
import onboardingCheck from "~/components/utilities/checks/OnboardingCheck";
import { TabsObject } from "~/components/v2/Tabs";
import {
decryptAssymmetric,
encryptAssymmetric
} from "../../components/utilities/cryptography/crypto";
import getOrganizationUsers from "../api/organization/GetOrgUsers";
import getUser from "../api/user/getUser";
import registerUserAction from "../api/userActions/registerUserAction";
// import DeleteUserDialog from '@app/components/basic/dialog/DeleteUserDialog';
import addUserToWorkspace from "../api/workspace/addUserToWorkspace";
import getWorkspaceUsers from "../api/workspace/getWorkspaceUsers";
import uploadKeys from "../api/workspace/uploadKeys";
interface UserProps {
firstName: string;
lastName: string;
email: string;
_id: string;
publicKey: string;
}
interface MembershipProps {
deniedPermissions: any[];
user: UserProps;
inviteEmail: string;
role: string;
status: string;
_id: string;
}
const features = [{
"_id": 0,
"name": "Kubernetes Operator",
"description": "Pull secrets into your Kubernetes containers and automatically redeploy upon secret changes."
}]
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 (
<a
target={`${link.includes("https") ? "_blank" : "_self"}`}
rel="noopener noreferrer"
className={`w-full ${complete && "opacity-30 duration-200 hover:opacity-100"}`}
href={link}
>
<div className={`${complete ? "bg-gradient-to-r from-primary-500/70 p-[0.07rem]" : ""} mb-3 rounded-md`}>
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={async () => {
if (userAction && userAction !== "first_time_secrets_pushed") {
await registerUserAction({
action: userAction
});
}
}}
className={`group relative flex h-[5.5rem] w-full items-center justify-between overflow-hidden rounded-md border ${complete? "bg-gradient-to-r from-[#0e1f01] to-mineshaft-700 border-mineshaft-900 cursor-default" : "bg-mineshaft-800 hover:bg-mineshaft-700 border-mineshaft-600 shadow-xl cursor-pointer"} duration-200 text-mineshaft-100`}
>
<div className="mr-4 flex flex-row items-center">
<FontAwesomeIcon icon={icon} className="mx-2 w-16 text-4xl" />
{complete && (
<div className="absolute left-12 top-10 flex h-7 w-7 items-center justify-center rounded-full bg-bunker-500 p-2 group-hover:bg-mineshaft-700">
<FontAwesomeIcon icon={faCheckCircle} className="h-5 w-5 text-4xl text-primary" />
</div>
)}
<div className="flex flex-col items-start">
<div className="mt-0.5 text-xl font-semibold">{text}</div>
<div className="text-sm font-normal">{subText}</div>
</div>
</div>
<div
className={`w-32 pr-8 text-right text-sm font-semibold ${complete && "text-primary"}`}
>
{complete ? "Complete!" : `About ${time}`}
</div>
{/* {complete && <div className="absolute bottom-0 left-0 h-1 w-full bg-primary" />} */}
</div>
</div>
</a>
);
}
return (
<div
onKeyDown={() => null}
role="button"
tabIndex={0}
onClick={async () => {
if (userAction) {
await registerUserAction({
action: userAction
});
}
}}
className="relative my-1.5 flex h-[5.5rem] w-full cursor-pointer items-center justify-between overflow-hidden rounded-md border border-dashed border-bunker-400 bg-bunker-700 py-2 pl-2 pr-6 shadow-xl duration-200 hover:bg-bunker-500"
>
<div className="mr-4 flex flex-row items-center">
<FontAwesomeIcon icon={icon} className="mx-2 w-16 text-4xl" />
{complete && (
<div className="absolute left-11 top-10 h-7 w-7 rounded-full bg-bunker-700">
<FontAwesomeIcon
icon={faCheckCircle}
className="absolute left-12 top-16 h-5 w-5 text-4xl text-primary"
/>
</div>
)}
<div className="flex flex-col items-start">
<div className="mt-0.5 text-xl font-semibold">{text}</div>
<div className="mt-0.5 text-sm font-normal">{subText}</div>
</div>
</div>
<div className={`w-28 pr-4 text-right text-sm font-semibold ${complete && "text-primary"}`}>
{complete ? "Complete!" : `About ${time}`}
</div>
{complete && <div className="absolute bottom-0 left-0 h-1 w-full bg-primary" />}
</div>
);
};
// #TODO: Update all the workspaceIds
export default function Organization() {
const [isAddOpen, setIsAddOpen] = useState(false);
// let [isDeleteOpen, setIsDeleteOpen] = useState(false);
// let [userIdToBeDeleted, setUserIdToBeDeleted] = useState(false);
const [email, setEmail] = useState("");
const [personalEmail, setPersonalEmail] = useState("");
const [searchUsers, setSearchUsers] = useState("");
const { t } = useTranslation();
const router = useRouter();
const workspaceId = router.query.id as string;
const [userList, setUserList] = useState<any[]>([]);
const [isUserListLoading, setIsUserListLoading] = useState(true);
const [orgUserList, setOrgUserList] = useState<any[]>([]);
const { workspaces, isLoading: isWorkspaceLoading } = useWorkspace();
useEffect(() => {
(async () => {
const user = await getUser();
setPersonalEmail(user.email);
// This part quiries the current users of a project
const workspaceUsers = await getWorkspaceUsers({
workspaceId
});
const tempUserList = workspaceUsers.map((membership: MembershipProps) => ({
key: guidGenerator(),
firstName: membership.user?.firstName,
lastName: membership.user?.lastName,
email: membership.user?.email === null ? membership.inviteEmail : membership.user?.email,
role: membership?.role,
status: membership?.status,
userId: membership.user?._id,
membershipId: membership._id,
deniedPermissions: membership.deniedPermissions,
publicKey: membership.user?.publicKey
}));
setUserList(tempUserList);
setIsUserListLoading(false);
// This is needed to know wha users from an org (if any), we are able to add to a certain project
const orgUsers = await getOrganizationUsers({
orgId: String(localStorage.getItem("orgData.id"))
});
setOrgUserList(orgUsers);
setEmail(
orgUsers
?.filter((membership: MembershipProps) => membership.status === "accepted")
.map((membership: MembershipProps) => membership.user.email)
.filter(
(usEmail: string) =>
!tempUserList?.map((user1: UserProps) => user1.email).includes(usEmail)
)[0]
);
})();
}, []);
const closeAddModal = () => {
setIsAddOpen(false);
};
const openAddModal = () => {
setIsAddOpen(true);
};
// function closeDeleteModal() {
// setIsDeleteOpen(false);
// }
// function deleteMembership(userId) {
// deleteUserFromWorkspace(userId, router.query.id)
// }
// function openDeleteModal() {
// setIsDeleteOpen(true);
// }
const submitAddModal = async () => {
const result = await addUserToWorkspace(email, workspaceId);
if (result?.invitee && result?.latestKey) {
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
// assymmetrically decrypt symmetric key with local private key
const key = decryptAssymmetric({
ciphertext: result.latestKey.encryptedKey,
nonce: result.latestKey.nonce,
publicKey: result.latestKey.sender.publicKey,
privateKey: PRIVATE_KEY
});
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: key,
publicKey: result.invitee.publicKey,
privateKey: PRIVATE_KEY
});
uploadKeys(workspaceId, result.invitee._id, ciphertext, nonce);
}
setEmail("");
setIsAddOpen(false);
router.rel
oad();
};
const [hasUserClickedSlack, setHasUserClickedSlack] = useState(false);
const [hasUserClickedIntro, setHasUserClickedIntro] = useState(false);
const [hasUserStarred, setHasUserStarred] = useState(false);
const [hasUserPushedSecrets, setHasUserPushedSecrets] = useState(false);
const [usersInOrg, setUsersInOrg] = useState(false);
useEffect(() => {
onboardingCheck({
setHasUserClickedIntro,
setHasUserClickedSlack,
setHasUserPushedSecrets,
setHasUserStarred,
setUsersInOrg
});
}, []);
return userList ? (
<div className="flex max-w-7xl mx-auto flex-col justify-start bg-bunker-800 md:h-screen">
<Head>
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
<link rel="icon" href="/infisical.ico" />
</Head>
<div className="flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl mb-4">
<p className="mr-4 font-semibold text-white">Projects</p>
<div className="mt-4 w-full grid grid-flow-dense gap-4" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(256px, 4fr))" }}>
{workspaces.map(workspace => <div key={workspace._id} className="h-40 w-72 rounded-md bg-mineshaft-800 border border-mineshaft-600 p-4 flex flex-col justify-between">
<div className="text-lg text-mineshaft-100 mt-0">{workspace.name}</div>
<div className="text-sm text-mineshaft-300 mt-0 pb-6">{(workspace.environments?.length || 0)} environments</div>
<Link href="/dashbaord">
<div className="group cursor-default ml-auto hover:bg-primary-800/20 text-sm text-mineshaft-300 hover:text-mineshaft-200 bg-mineshaft-900 py-2 px-4 rounded-full w-max border border-mineshaft-600 hover:border-primary-500/80">Explore <FontAwesomeIcon icon={faArrowRight} className="pl-1.5 pr-0.5 group-hover:pl-2 group-hover:pr-0 duration-200" /></div>
</Link>
</div>)}
</div>
</div>
<div className="flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl mb-4">
<p className="mr-4 font-semibold text-white mb-4">Onboarding Guide</p>
{learningItem({
text: "Watch a video about Infisical",
subText: "",
complete: hasUserClickedIntro,
icon: faHandPeace,
time: "3 min",
userAction: "intro_cta_clicked",
link: "https://www.youtube.com/watch?v=PK23097-25I"
})}
{learningItem({
text: "Add your secrets",
subText: "Click to see example secrets, and add your own.",
complete: hasUserPushedSecrets,
icon: faPlus,
time: "1 min",
userAction: "first_time_secrets_pushed",
link: `/dashboard/${router.query.id}`
})}
<div className="group text-mineshaft-100 relative mb-3 flex h-full w-full cursor-default flex-col items-center justify-between overflow-hidden rounded-md border border-mineshaft-600 bg-bunker-500 pl-2 pr-2 pt-4 pb-2 shadow-xl duration-200">
<div className="mb-4 flex w-full flex-row items-center pr-4">
<div className="mr-4 flex w-full flex-row items-center">
<FontAwesomeIcon icon={faNetworkWired} className="mx-2 w-16 text-4xl" />
{false && (
<div className="absolute left-12 top-10 flex h-7 w-7 items-center justify-center rounded-full bg-bunker-500 p-2 group-hover:bg-mineshaft-700">
<FontAwesomeIcon icon={faCheckCircle} className="h-5 w-5 text-4xl text-green" />
</div>
)}
<div className="flex flex-col items-start pl-0.5">
<div className="mt-0.5 text-xl font-semibold">Inject secrets locally</div>
<div className="text-sm font-normal">
Replace .env files with a more secure and efficient alternative.
</div>
</div>
</div>
<div className={`w-28 pr-4 text-right text-sm font-semibold ${false && "text-green"}`}>
About 2 min
</div>
</div>
<TabsObject />
{false && <div className="absolute bottom-0 left-0 h-1 w-full bg-green" />}
</div>
{learningItem({
text: "Integrate Infisical with your infrastructure",
subText: "Connect Infisical to various 3rd party services and platforms.",
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-1wehzfnzn-1aMo5JcGENJiNAC2SD8Jlg"
})}
{/* <div className="mt-4 w-full grid grid-flow-dense gap-4" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(256px, 4fr))" }}>
{workspaces.map(workspace => <div key={workspace._id} className="h-40 w-72 rounded-md bg-mineshaft-800 border border-mineshaft-600 p-4 flex flex-col justify-between">
<div className="text-lg text-mineshaft-100 mt-0">{workspace.name}</div>
<Link href="/dashbaord">
<div className="group cursor-default hover:bg-primary-800/20 text-sm text-mineshaft-300 hover:text-mineshaft-200 bg-mineshaft-900 py-2 px-4 rounded-full w-max border border-mineshaft-600 hover:border-primary-500/80">Explore <FontAwesomeIcon icon={faArrowRight} className="pl-1.5 pr-0.5 group-hover:pl-2 group-hover:pr-0 duration-200" /></div>
</Link>
</div>)}
</div> */}
</div>
<div className="flex flex-col items-start justify-start px-6 py-6 pb-0 text-3xl mb-4 pb-6">
<p className="mr-4 font-semibold text-white">Explore More</p>
<div className="mt-4 w-full grid grid-flow-dense gap-4" style={{ gridTemplateColumns: "repeat(auto-fill, minmax(256px, 4fr))" }}>
{features.map(feature => <div key={feature._id} className="h-44 w-96 rounded-md bg-mineshaft-800 border border-mineshaft-600 p-4 flex flex-col justify-between">
<div className="text-lg text-mineshaft-100 mt-0">{feature.name}</div>
<div className="text-[15px] font-light text-mineshaft-300 mb-4 mt-2">{feature.description}</div>
<div className="w-full flex items-center">
<div className="text-mineshaft-300 text-[15px] font-light">Setup time: 20 min</div>
<Link href="/dashbaord">
<div className="group cursor-default ml-auto hover:bg-primary-800/20 text-sm text-mineshaft-300 hover:text-mineshaft-200 bg-mineshaft-900 py-2 px-4 rounded-full w-max border border-mineshaft-600 hover:border-primary-500/80">Learn more <FontAwesomeIcon icon={faArrowRight} className="pl-1.5 pr-0.5 group-hover:pl-2 group-hover:pr-0 duration-200" /></div>
</Link>
</div>
</div>)}
</div>
</div>
<AddProjectMemberDialog
isOpen={isAddOpen}
closeModal={closeAddModal}
submitModal={submitAddModal}
email={email}
data={orgUserList
?.filter((membership: MembershipProps) => membership.status === "accepted")
.map((membership: MembershipProps) => membership.user.email)
.filter(
(orgEmail) => !userList?.map((user1: UserProps) => user1.email).includes(orgEmail)
)}
setEmail={setEmail}
/>
{/* <DeleteUserDialog isOpen={isDeleteOpen} closeModal={closeDeleteModal} submitModal={deleteMembership} userIdToBeDeleted={userIdToBeDeleted}/> */}
{/* <div className="absolute right-4 top-36 flex w-full flex-row items-start px-6 pb-1">
<div className="flex w-full max-w-sm flex flex-row ml-auto">
<Input
className="h-[2.3rem] bg-mineshaft-800 placeholder-mineshaft-50 duration-200 focus:bg-mineshaft-700/80"
placeholder="Search by users..."
value={searchUsers}
onChange={(e) => setSearchUsers(e.target.value)}
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
/>
</div>
<div className="ml-2 flex min-w-max flex-row items-start justify-start">
<Button
text={String(t("section.members.add-member"))}
onButtonPressed={openAddModal}
color="mineshaft"
size="md"
icon={faPlus}
/>
</div>
</div> */}
</div>
) : (
<div className="relative z-10 mr-auto ml-2 flex h-full w-10/12 flex-col items-center justify-center bg-bunker-800">
<Image src="/images/loading/loading.gif" height={70} width={120} alt="loading animation" />
</div>
);
}
Organization.requireAuth = true;

View File

@ -1245,17 +1245,17 @@ module.exports = {
colors: {
// You can generate your own colors with this tool: https://javisperez.github.io/tailwindcolorshades/
primary: {
50: '#fcfdf7',
100: '#f8fcee',
200: '#eef6d5',
300: '#e3f1bc',
400: '#cfe78a',
500: '#badc58',
600: '#a7c64f',
700: '#8ca542',
800: '#708435',
900: '#5b6c2b',
DEFAULT: '#badc58'
50: '#fffff5',
100: '#fcfce8',
200: '#f8faca',
300: '#f4f7ab',
400: '#ecf26d',
500: '#e0ed34',
600: '#c2d62b',
700: '#97b31d',
800: '#708f13',
900: '#4d6b0b',
DEFAULT: '#e0ed34'
},
grey: '#0d1117',
mineshaft: {
@ -1339,7 +1339,31 @@ module.exports = {
800: '#1c7a44',
900: '#176437',
DEFAULT: '#2ecc71'
}
},
blue: {
50: '#f2f8ff',
100: '#e6f1ff',
200: '#bfdbff',
300: '#99c5ff',
400: '#4d9aff',
500: '#006eff',
600: '#0063e6',
700: '#0053bf',
800: '#004299',
900: '#00367d'
},
darkblue: {
50: '#f2f4f7',
100: '#e6e8f0',
200: '#bfc6d9',
300: '#99a3c3',
400: '#4d5f95',
500: '#001a68',
600: '#00175e',
700: '#00144e',
800: '#00103e',
900: '#000d33'
},
},
keyframes: {
type: {