mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 18:41:21 +00:00
feat(ui): implemented the new project settings page
This commit is contained in:
@@ -187,10 +187,10 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
});
|
||||
const userWorkspaces = orgUserProjects;
|
||||
if (
|
||||
userWorkspaces.length === 0 &&
|
||||
router.asPath !== '/noprojects' &&
|
||||
!router.asPath.includes('home') &&
|
||||
!router.asPath.includes('settings') ||
|
||||
(userWorkspaces.length === 0 &&
|
||||
router.asPath !== '/noprojects' &&
|
||||
!router.asPath.includes('home') &&
|
||||
!router.asPath.includes('settings')) ||
|
||||
router.asPath === '/dashboard/undefined'
|
||||
) {
|
||||
router.push('/noprojects');
|
||||
@@ -246,16 +246,15 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fixed w-full md:block flex flex-col h-screen">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.2.2/cdn.js" defer />
|
||||
<div className="flex h-screen w-full flex-col overflow-x-hidden">
|
||||
<NavBarDashboard />
|
||||
<div className="flex flex-col md:flex-row flex-1">
|
||||
<aside className="bg-bunker-600 border-r border-mineshaft-500 w-full md:w-60 h-screen">
|
||||
<nav className="flex flex-col justify-between items-between h-full">
|
||||
<div className="flex flex-grow flex-col overflow-y-hidden md:flex-row">
|
||||
<aside className="w-full border-r border-mineshaft-500 bg-bunker-600 md:w-60">
|
||||
<nav className="items-between flex h-full flex-col justify-between">
|
||||
{/* <div className="py-6"></div> */}
|
||||
<div>
|
||||
<div className="flex justify-center w-full mt-[4.5rem] mb-6 bg-bunker-600 h-20 flex-col items-center px-4">
|
||||
<div className="text-gray-400 self-start ml-1 mb-1 text-xs font-semibold tracking-wide">
|
||||
<div className="mt-6 mb-6 flex h-20 w-full flex-col items-center justify-center bg-bunker-600 px-4">
|
||||
<div className="ml-1 mb-1 self-start text-xs font-semibold tracking-wide text-gray-400">
|
||||
{t('nav:menu.project')}
|
||||
</div>
|
||||
{Object.keys(workspaceMapping).length > 0 ? (
|
||||
@@ -279,29 +278,29 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
<ul>
|
||||
{Object.keys(workspaceMapping).length > 0 &&
|
||||
menuItems.map(({ href, title, emoji }) => (
|
||||
<li className="mt-0.5 mx-2" key={title}>
|
||||
<li className="mx-2 mt-0.5" key={title}>
|
||||
{router.asPath.split('/')[1] === href.split('/')[1] &&
|
||||
(['project', 'billing', 'org', 'personal'].includes(
|
||||
router.asPath.split('/')[2]
|
||||
)
|
||||
? router.asPath.split('/')[2] === href.split('/')[2]
|
||||
: true) ? (
|
||||
<div className="flex relative px-0.5 py-2.5 text-white text-sm rounded cursor-pointer bg-primary-50/10">
|
||||
<div className="absolute top-0 my-1 ml-1 inset-0 bg-primary w-1 rounded-xl mr-1" />
|
||||
<p className="w-6 ml-4 mr-2 flex items-center justify-center text-lg">
|
||||
<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">
|
||||
{emoji}
|
||||
</p>
|
||||
{title}
|
||||
</div>
|
||||
) : router.asPath === '/noprojects' ? (
|
||||
<div className="flex p-2.5 text-white text-sm rounded">
|
||||
<p className="w-10 flex items-center justify-center text-lg">{emoji}</p>
|
||||
<div className="flex rounded p-2.5 text-sm text-white">
|
||||
<p className="flex w-10 items-center justify-center text-lg">{emoji}</p>
|
||||
{title}
|
||||
</div>
|
||||
) : (
|
||||
<Link href={href}>
|
||||
<div className="flex p-2.5 text-white text-sm rounded cursor-pointer hover:bg-primary-50/5">
|
||||
<p className="w-10 flex items-center justify-center text-lg">
|
||||
<div className="flex cursor-pointer rounded p-2.5 text-sm text-white hover:bg-primary-50/5">
|
||||
<p className="flex w-10 items-center justify-center text-lg">
|
||||
{emoji}
|
||||
</p>
|
||||
{title}
|
||||
@@ -312,11 +311,11 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div className="w-full mt-40 mb-4 px-2">
|
||||
<div className="mt-40 mb-4 w-full px-2">
|
||||
{router.asPath.split('/')[1] === 'home' ? (
|
||||
<div className="flex relative px-0.5 py-2.5 text-white text-sm rounded cursor-pointer bg-primary-50/10">
|
||||
<div className="absolute top-0 my-1 ml-1 inset-0 bg-primary w-1 rounded-xl mr-1" />
|
||||
<p className="w-6 ml-4 mr-2 flex items-center justify-center text-lg">
|
||||
<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
|
||||
@@ -336,8 +335,8 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
</div>
|
||||
) : (
|
||||
<Link href={`/home/${workspaceMapping[workspaceSelected as any]}`}>
|
||||
<div className="relative flex p-2.5 overflow-visible text-white h-10 text-sm rounded cursor-pointer bg-white/10 hover:bg-primary-50/[0.15] mt-max">
|
||||
<p className="w-10 flex items-center justify-center text-lg">
|
||||
<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
|
||||
@@ -369,12 +368,12 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
error={error}
|
||||
loading={loading}
|
||||
/>
|
||||
<main className="flex-1 bg-bunker-800">{children}</main>
|
||||
<main className="flex-1 overflow-y-auto overflow-x-hidden bg-bunker-800">{children}</main>
|
||||
</div>
|
||||
</div>
|
||||
<div className="md:hidden bg-bunker-800 w-screen h-screen flex flex-col justify-center items-center">
|
||||
<FontAwesomeIcon icon={faMobile} className="text-gray-300 text-7xl mb-8" />
|
||||
<p className="text-gray-200 px-6 text-center text-lg max-w-sm">
|
||||
<div className="flex h-screen w-screen flex-col items-center justify-center bg-bunker-800 md:hidden">
|
||||
<FontAwesomeIcon icon={faMobile} className="mb-8 text-7xl text-gray-300" />
|
||||
<p className="max-w-sm px-6 text-center text-lg text-gray-200">
|
||||
{` ${t('common:no-mobile')} `}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,6 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
||||
const onEnvCreateCB = async (env: Env) => {
|
||||
try {
|
||||
await onCreateEnv(env);
|
||||
@@ -71,14 +70,14 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-row justify-between w-full">
|
||||
<div className="flex flex-col w-full">
|
||||
<p className="text-xl font-semibold mb-3">Project Environments</p>
|
||||
<p className="text-base text-gray-400 mb-4">
|
||||
<div className="flex w-full flex-row justify-between">
|
||||
<div className="flex w-full flex-col">
|
||||
<p className="mb-3 text-xl font-semibold">Project Environments</p>
|
||||
<p className="mb-4 text-base text-gray-400">
|
||||
Choose which environments will show up in your dashboard like development, staging,
|
||||
production
|
||||
</p>
|
||||
<p className="text-sm mr-1 text-gray-500 self-start">
|
||||
<p className="mr-1 self-start text-sm text-gray-500">
|
||||
Note: the text in slugs shows how these environmant should be accessed in CLI.
|
||||
</p>
|
||||
</div>
|
||||
@@ -86,10 +85,10 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
<Button
|
||||
text="Add New Env"
|
||||
onButtonPressed={() => {
|
||||
if (plan !== plans.starter || host !== "https://app.infisical.com") {
|
||||
handlePopUpOpen('createUpdateEnv')
|
||||
if (plan !== plans.starter || host !== 'https://app.infisical.com') {
|
||||
handlePopUpOpen('createUpdateEnv');
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan')
|
||||
handlePopUpOpen('upgradePlan');
|
||||
}
|
||||
}}
|
||||
color="mineshaft"
|
||||
@@ -98,32 +97,30 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="table-container w-full bg-bunker rounded-md mb-6 border border-mineshaft-700 relative mt-1">
|
||||
<div className="absolute rounded-t-md w-full h-12 bg-white/5" />
|
||||
<table className="w-full my-1">
|
||||
<div className="table-container relative mb-6 mt-1 w-full rounded-md border border-mineshaft-700 bg-bunker">
|
||||
<div className="absolute h-12 w-full rounded-t-md bg-white/5" />
|
||||
<table className="my-1 w-full">
|
||||
<thead className="text-bunker-300">
|
||||
<tr>
|
||||
<th className="text-left pl-6 pt-2.5 pb-2">Name</th>
|
||||
<th className="text-left pl-6 pt-2.5 pb-2">Slug</th>
|
||||
<th className="pl-6 pt-2.5 pb-2 text-left">Name</th>
|
||||
<th className="pl-6 pt-2.5 pb-2 text-left">Slug</th>
|
||||
<th aria-label="buttons" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data?.length > 0 ? (
|
||||
data.map(({ name, slug }) => (
|
||||
<tr key={name} className="bg-bunker-800 hover:bg-bunker-800/5 duration-100">
|
||||
<td className="pl-6 py-2 border-mineshaft-700 border-t text-gray-300">
|
||||
{name}
|
||||
</td>
|
||||
<td className="pl-6 py-2 border-mineshaft-700 border-t text-gray-300">{slug}</td>
|
||||
<td className="py-2 border-mineshaft-700 border-t flex justify-end">
|
||||
<div className="hover:opacity-100 duration-200 flex items-center mr-2">
|
||||
<tr key={name} className="bg-bunker-800 duration-100 hover:bg-bunker-800/5">
|
||||
<td className="border-t border-mineshaft-700 py-2 pl-6 text-gray-300">{name}</td>
|
||||
<td className="border-t border-mineshaft-700 py-2 pl-6 text-gray-300">{slug}</td>
|
||||
<td className="flex justify-end border-t border-mineshaft-700 py-2">
|
||||
<div className="mr-2 flex items-center duration-200 hover:opacity-100">
|
||||
<Button
|
||||
onButtonPressed={() => {
|
||||
if (plan !== plans.starter || host !== "https://app.infisical.com") {
|
||||
handlePopUpOpen('createUpdateEnv', { name, slug })
|
||||
if (plan !== plans.starter || host !== 'https://app.infisical.com') {
|
||||
handlePopUpOpen('createUpdateEnv', { name, slug });
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan')
|
||||
handlePopUpOpen('upgradePlan');
|
||||
}
|
||||
}}
|
||||
color="mineshaft"
|
||||
@@ -131,13 +128,13 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
icon={faPencil}
|
||||
/>
|
||||
</div>
|
||||
<div className="opacity-50 hover:opacity-100 duration-200 flex items-center mr-6">
|
||||
<div className="mr-6 flex items-center opacity-50 duration-200 hover:opacity-100">
|
||||
<Button
|
||||
onButtonPressed={() => {
|
||||
if (plan !== plans.starter || host !== "https://app.infisical.com") {
|
||||
handlePopUpOpen('deleteEnv', { name, slug })
|
||||
if (plan !== plans.starter || host !== 'https://app.infisical.com') {
|
||||
handlePopUpOpen('deleteEnv', { name, slug });
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan')
|
||||
handlePopUpOpen('upgradePlan');
|
||||
}
|
||||
}}
|
||||
color="red"
|
||||
@@ -150,7 +147,7 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
))
|
||||
) : (
|
||||
<tr>
|
||||
<td colSpan={4} className="text-center pt-7 pb-4 text-bunker-400">
|
||||
<td colSpan={4} className="pt-7 pb-4 text-center text-bunker-400">
|
||||
No environmants found
|
||||
</td>
|
||||
</tr>
|
||||
@@ -174,7 +171,7 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
onCreateSubmit={onEnvCreateCB}
|
||||
onEditSubmit={onEnvUpdateCB}
|
||||
/>
|
||||
<UpgradePlanModal
|
||||
<UpgradePlanModal
|
||||
isOpen={popUp.upgradePlan.isOpen}
|
||||
onClose={() => handlePopUpClose('upgradePlan')}
|
||||
text="You can add custom environments if you switch to Infisical's Team plan."
|
||||
|
||||
@@ -71,7 +71,7 @@ const SideBar = ({
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="absolute border-l border-mineshaft-500 bg-bunker h-full w-96 top-14 right-0 z-40 shadow-xl flex flex-col justify-between">
|
||||
<div className="absolute border-l border-mineshaft-500 bg-bunker h-full w-96 right-0 z-40 shadow-xl flex flex-col justify-between">
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<Image
|
||||
@@ -171,7 +171,7 @@ const SideBar = ({
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-start max-w-sm mt-4 px-4 mt-full mb-[4.7rem]">
|
||||
<div className="flex justify-start max-w-sm mt-4 px-4 mt-full mb-8">
|
||||
<Button
|
||||
text={String(t('common:save-changes'))}
|
||||
onButtonPressed={savePush}
|
||||
|
||||
@@ -93,7 +93,7 @@ export default function Navbar() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="absolute flex flex-row justify-between w-full bg-bunker text-white border-b border-mineshaft-500 z-50">
|
||||
<div className="flex flex-row justify-between w-full bg-bunker text-white border-b border-mineshaft-500 z-50">
|
||||
<div className="m-auto flex justify-start items-center mx-4">
|
||||
<div className="flex flex-row items-center">
|
||||
<div className="flex justify-center py-4">
|
||||
|
||||
@@ -3,8 +3,8 @@ import { useRouter } from 'next/router';
|
||||
import { faAngleRight } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
import { useWorkspace } from '@app/context';
|
||||
import getOrganization from '@app/pages/api/organization/GetOrg';
|
||||
import getProjectInfo from '@app/pages/api/workspace/getProjectInfo';
|
||||
|
||||
/**
|
||||
* This is the component at the top of almost every page.
|
||||
@@ -23,9 +23,9 @@ export default function NavHeader({
|
||||
isProjectRelated?: boolean;
|
||||
}): JSX.Element {
|
||||
const [orgName, setOrgName] = useState('');
|
||||
const [workspaceName, setWorkspaceName] = useState('');
|
||||
const router = useRouter();
|
||||
const projectId = String(router.query.id);
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
@@ -34,29 +34,24 @@ export default function NavHeader({
|
||||
orgId: orgId || ''
|
||||
});
|
||||
setOrgName(org.name);
|
||||
|
||||
const workspace = await getProjectInfo({
|
||||
projectId
|
||||
});
|
||||
setWorkspaceName(workspace.name);
|
||||
})();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [projectId]);
|
||||
|
||||
return (
|
||||
<div className="pt-20 ml-6 flex flex-row items-center">
|
||||
<div className="bg-primary-900 h-6 w-6 rounded-md flex items-center justify-center text-mineshaft-100 mr-2">
|
||||
<div className="ml-6 flex flex-row items-center pt-8">
|
||||
<div className="mr-2 flex h-6 w-6 items-center justify-center rounded-md bg-primary-900 text-mineshaft-100">
|
||||
{orgName?.charAt(0)}
|
||||
</div>
|
||||
<div className="text-primary text-sm font-semibold">{orgName}</div>
|
||||
<div className="text-sm font-semibold text-primary">{orgName}</div>
|
||||
{isProjectRelated && (
|
||||
<>
|
||||
<FontAwesomeIcon icon={faAngleRight} className="ml-3 text-sm text-gray-400 mr-3" />
|
||||
<div className="font-semibold text-primary text-sm">{workspaceName}</div>
|
||||
<FontAwesomeIcon icon={faAngleRight} className="ml-3 mr-3 text-sm text-gray-400" />
|
||||
<div className="text-sm font-semibold text-primary">{currentWorkspace?.name}</div>
|
||||
</>
|
||||
)}
|
||||
<FontAwesomeIcon icon={faAngleRight} className="ml-3 text-sm text-gray-400 mr-3" />
|
||||
<div className="text-gray-400 text-sm">{pageName}</div>
|
||||
<FontAwesomeIcon icon={faAngleRight} className="ml-3 mr-3 text-sm text-gray-400" />
|
||||
<div className="text-sm text-gray-400">{pageName}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user