diff --git a/frontend/src/pages/org/[id]/overview/index.tsx b/frontend/src/pages/org/[id]/overview/index.tsx
index 17cf8537c6..e5d4ffc3cc 100644
--- a/frontend/src/pages/org/[id]/overview/index.tsx
+++ b/frontend/src/pages/org/[id]/overview/index.tsx
@@ -17,10 +17,14 @@ import {
faClipboard,
faExclamationCircle,
faHandPeace,
+ faList,
faMagnifyingGlass,
faNetworkWired,
faPlug,
faPlus,
+ faProjectDiagram,
+ faTableCells,
+ faTableColumns,
faUserPlus
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@@ -34,6 +38,9 @@ import onboardingCheck from "@app/components/utilities/checks/OnboardingCheck";
import {
Button,
Checkbox,
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuTrigger,
FormControl,
Input,
Modal,
@@ -86,6 +93,11 @@ type ItemProps = {
link?: string;
};
+enum ProjectsViewMode {
+ GRID = "grid",
+ LIST = "list"
+}
+
function copyToClipboard(id: string, setState: (value: boolean) => void) {
// Get the text field
const copyText = document.getElementById(id) as HTMLInputElement;
@@ -309,8 +321,9 @@ const LearningItem = ({
href={link}
>
null}
@@ -321,10 +334,11 @@ const LearningItem = ({
await registerUserAction.mutateAsync(userAction);
}
}}
- className={`group relative flex h-[5.5rem] w-full items-center justify-between overflow-hidden rounded-md border ${complete
+ className={`group relative flex h-[5.5rem] w-full items-center justify-between overflow-hidden rounded-md border ${
+ complete
? "cursor-default border-mineshaft-900 bg-gradient-to-r from-[#0e1f01] to-mineshaft-700"
: "cursor-pointer border-mineshaft-600 bg-mineshaft-800 shadow-xl hover:bg-mineshaft-700"
- } text-mineshaft-100 duration-200`}
+ } text-mineshaft-100 duration-200`}
>
@@ -402,8 +416,9 @@ const LearningItemSquare = ({
href={link}
>
null}
@@ -414,10 +429,11 @@ const LearningItemSquare = ({
await registerUserAction.mutateAsync(userAction);
}
}}
- className={`group relative flex w-full items-center justify-between overflow-hidden rounded-md border ${complete
+ className={`group relative flex w-full items-center justify-between overflow-hidden rounded-md border ${
+ complete
? "cursor-default border-mineshaft-900 bg-gradient-to-r from-[#0e1f01] to-mineshaft-700"
: "cursor-pointer border-mineshaft-600 bg-mineshaft-800 shadow-xl hover:bg-mineshaft-700"
- } text-mineshaft-100 duration-200`}
+ } text-mineshaft-100 duration-200`}
>
@@ -431,8 +447,9 @@ const LearningItemSquare = ({
)}
{complete ? "Complete!" : `About ${time}`}
@@ -496,6 +513,9 @@ const OrganizationPage = withPermission(
const createWs = useCreateWorkspace();
const { user } = useUser();
const { data: serverDetails } = useFetchServerStatus();
+ const [projectsViewMode, setProjectsViewMode] = useState
(
+ (localStorage.getItem("projectsViewMode") as ProjectsViewMode) || ProjectsViewMode.GRID
+ );
const onCreateProject = async ({ name, addMembers }: TAddProjectFormData) => {
// type check
@@ -551,6 +571,90 @@ const OrganizationPage = withPermission(
const isWorkspaceEmpty = !isWorkspaceLoading && orgWorkspaces?.length === 0;
+ const projectsGridView = (
+
+ {isWorkspaceLoading &&
+ Array.apply(0, Array(3)).map((_x, i) => (
+
+ ))}
+ {orgWorkspaces
+ .filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
+ .map((workspace) => (
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
+
{
+ router.push(`/project/${workspace.id}/secrets/overview`);
+ localStorage.setItem("projectData.id", workspace.id);
+ }}
+ key={workspace.id}
+ className="min-w-72 group flex h-40 cursor-pointer flex-col justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
+ >
+
{workspace.name}
+
+ {workspace.environments?.length || 0} environments
+
+
+
+ ))}
+
+ );
+
+ const projectsListView = (
+
+ {isWorkspaceLoading &&
+ Array.apply(0, Array(3)).map((_x, i) => (
+
+
+
+ ))}
+ {orgWorkspaces
+ .filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
+ .map((workspace) => (
+ // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
+
{
+ router.push(`/project/${workspace.id}/secrets/overview`);
+ localStorage.setItem("projectData.id", workspace.id);
+ }}
+ key={workspace.id}
+ className="min-w-72 group flex h-12 cursor-pointer flex-row items-center justify-between border border-mineshaft-600 bg-mineshaft-800 px-6 hover:bg-mineshaft-700"
+ >
+
+
+ {workspace.environments?.length || 0} environments
+
+
+ ))}
+
+ );
+
return (
@@ -580,7 +684,44 @@ const OrganizationPage = withPermission(
)}
-
Projects
+
+
Projects
+
+
+ }>
+ Display
+
+
+
+
+ }
+ onClick={() => {
+ localStorage.setItem("projectsViewMode", ProjectsViewMode.GRID);
+ setProjectsViewMode(ProjectsViewMode.GRID);
+ }}
+ variant="outline_bg"
+ className="h-10 text-left"
+ isFullWidth
+ >
+ Grid
+
+ }
+ onClick={() => {
+ localStorage.setItem("projectsViewMode", ProjectsViewMode.LIST);
+ setProjectsViewMode(ProjectsViewMode.LIST);
+ }}
+ variant="outline_bg"
+ className="h-10 text-left"
+ isFullWidth
+ >
+ List
+
+
+
+
+
-
- {isWorkspaceLoading &&
- Array.apply(0, Array(3)).map((_x, i) => (
-
- ))}
- {orgWorkspaces
- .filter((ws) => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase()))
- .map((workspace) => (
- // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
-
{
- router.push(`/project/${workspace.id}/secrets/overview`);
- localStorage.setItem("projectData.id", workspace.id);
- }}
- key={workspace.id}
- className="min-w-72 group flex h-40 cursor-pointer flex-col justify-between rounded-md border border-mineshaft-600 bg-mineshaft-800 p-4"
- >
-
{workspace.name}
-
- {workspace.environments?.length || 0} environments
-
-
-
- ))}
-
+ {projectsViewMode === ProjectsViewMode.LIST ? projectsListView : projectsGridView}
{isWorkspaceEmpty && (
- Onboarding Guide
-
-
- {orgWorkspaces.length !== 0 && (
- <>
-
-
- >
- )}
-
-
-
-
+
+
Onboarding Guide
+
+
{orgWorkspaces.length !== 0 && (
-
-
-
-
- {false && (
-
-
-
- )}
-
-
Inject secrets locally
-
- Replace .env files with a more secure and efficient alternative.
-
+ <>
+
+
+ >
+ )}
+
+
+
+
+ {orgWorkspaces.length !== 0 && (
+
+
+
+
+ {false && (
+
+
+
+ )}
+
+
Inject secrets locally
+
+ Replace .env files with a more secure and efficient alternative.
-
- About 2 min
-
-
- {false &&
}
+
+ About 2 min
+
- )}
- {orgWorkspaces.length !== 0 && (
-
- )}
-
- )}
+
+ {false &&
}
+
+ )}
+ {orgWorkspaces.length !== 0 && (
+
+ )}
+
+ )}
{