diff --git a/frontend/src/pages/pam/PamAccountsPage/components/AccountViewToggle.tsx b/frontend/src/pages/pam/PamAccountsPage/components/AccountViewToggle.tsx
index 51e568551..4448845cf 100644
--- a/frontend/src/pages/pam/PamAccountsPage/components/AccountViewToggle.tsx
+++ b/frontend/src/pages/pam/PamAccountsPage/components/AccountViewToggle.tsx
@@ -1,4 +1,7 @@
-import { Button } from "@app/components/v2";
+import { faBorderAll, faList } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+
+import { IconButton } from "@app/components/v2";
import { PamAccountView } from "@app/hooks/api/pam";
type Props = {
@@ -9,30 +12,32 @@ type Props = {
export const AccountViewToggle = ({ value, onChange }: Props) => {
return (
-
-
+
+ {
onChange(PamAccountView.Nested);
}}
+ ariaLabel="list"
size="xs"
className={`${
value === PamAccountView.Nested ? "bg-mineshaft-500" : "bg-transparent"
} min-w-[2.4rem] rounded border-none hover:bg-mineshaft-600`}
>
- Show Folders
-
+
+
);
};
diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountCard.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountCard.tsx
new file mode 100644
index 000000000..032483a63
--- /dev/null
+++ b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountCard.tsx
@@ -0,0 +1,51 @@
+import { Badge, UnstableButton } from "@app/components/v3";
+import { PAM_RESOURCE_TYPE_MAP, TPamAccount } from "@app/hooks/api/pam";
+import { LogInIcon, PackageOpenIcon } from "lucide-react";
+
+type Props = {
+ account: TPamAccount;
+ onAccess: (resource: TPamAccount) => void;
+ accountPath?: string;
+};
+
+export const PamAccountCard = ({ account, onAccess, accountPath }: Props) => {
+ const { name, description, resource } = account;
+
+ const { image, name: resourceTypeName } = PAM_RESOURCE_TYPE_MAP[account.resource.resourceType];
+
+ return (
+
+ );
+};
diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountRow.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountRow.tsx
index a2c668b27..c8196cf32 100644
--- a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountRow.tsx
+++ b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountRow.tsx
@@ -10,7 +10,7 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { formatDistance } from "date-fns";
-import { FolderIcon, PackageOpenIcon } from "lucide-react";
+import { PackageOpenIcon } from "lucide-react";
import { twMerge } from "tailwind-merge";
import { createNotification } from "@app/components/notifications";
@@ -39,8 +39,6 @@ type Props = {
onUpdate: (resource: TPamAccount) => void;
onDelete: (resource: TPamAccount) => void;
search: string;
- isFlatView: boolean;
- accountPath?: string;
isAccessLoading?: boolean;
};
@@ -50,8 +48,6 @@ export const PamAccountRow = ({
onAccess,
onUpdate,
onDelete,
- isFlatView,
- accountPath,
isAccessLoading
}: Props) => {
const { id, name } = account;
@@ -95,14 +91,6 @@ export const PamAccountRow = ({
- {isFlatView && accountPath && (
-
-
-
-
-
-
- )}
{"lastRotatedAt" in account && account.lastRotatedAt && (
{
setOrderDirection,
setOrderBy
} = usePagination(PamAccountOrderBy.Name, {
- initPerPage: getUserTablePreference("pamAccountsTable", PreferenceKey.PerPage, 20),
+ initPerPage: getUserTablePreference("pamAccountsTable", PreferenceKey.PerPage, 18),
initSearch
});
@@ -231,10 +232,25 @@ export const PamAccountsTable = ({ projectId }: Props) => {
const resources = resourcesData?.resources || [];
+ function accessAccount(account: TPamAccount) {
+ // For AWS IAM, directly open console without modal
+ if (account.resource.resourceType === PamResourceType.AwsIam) {
+ let fullAccountPath = account?.name;
+ const folderPath = account.folderId ? folderPaths[account.folderId] : undefined;
+ if (folderPath) {
+ const path = folderPath.replace(/^\/+|\/+$/g, "");
+ fullAccountPath = `${path}/${account?.name}`;
+ }
+
+ accessAwsIam(account, fullAccountPath);
+ } else {
+ handlePopUpOpen("accessAccount", account);
+ }
+ }
+
return (
-
- {accountView === PamAccountView.Nested &&
}
-
+
+
{(isAllowed) =>
isAllowed && (
@@ -392,32 +408,64 @@ export const PamAccountsTable = ({ projectId }: Props) => {
)}
-
-
-
-
- |
-
- Accounts
- handleSort(PamAccountOrderBy.Name)}
- >
-
-
-
- |
- |
-
-
-
- {isLoading && }
- {!isLoading && (
- <>
- {accountView !== PamAccountView.Flat &&
- foldersToRender.map((folder) => (
+ {accountView === PamAccountView.Nested && }
+ {accountView === PamAccountView.Flat ? (
+ <>
+
+ {filteredAccounts.map((account) => (
+
accessAccount(e)}
+ />
+ ))}
+
+ {!isLoading && isContentEmpty && (
+
+ )}
+ {Boolean(totalCount) && !isLoading && !isContentEmpty && (
+ setPage(newPage)}
+ onChangePerPage={handlePerPageChange}
+ perPageList={[9, 18, 48, 99]}
+ />
+ )}
+ >
+ ) : (
+
+
+
+
+ |
+
+ Accounts
+ handleSort(PamAccountOrderBy.Name)}
+ >
+
+
+
+ |
+ |
+
+
+
+ {isLoading && }
+ {!isLoading && (
+ <>
+ {foldersToRender.map((folder) => (
{
onDelete={(e) => handlePopUpOpen("deleteFolder", e)}
/>
))}
- {filteredAccounts.map((account) => (
- {
- // For AWS IAM, directly open console without modal
- if (e.resource.resourceType === PamResourceType.AwsIam) {
- let fullAccountPath = e?.name;
- const folderPath = e.folderId ? folderPaths[e.folderId] : undefined;
- if (folderPath) {
- const path = folderPath.replace(/^\/+|\/+$/g, "");
- fullAccountPath = `${path}/${e?.name}`;
- }
-
- accessAwsIam(e, fullAccountPath);
- } else {
- handlePopUpOpen("accessAccount", e);
- }
- }}
- onUpdate={(e) => handlePopUpOpen("updateAccount", e)}
- onDelete={(e) => handlePopUpOpen("deleteAccount", e)}
- />
- ))}
- >
- )}
-
-
- {Boolean(totalCount) && !isLoading && (
- setPage(newPage)}
- onChangePerPage={handlePerPageChange}
- />
- )}
- {!isLoading && isContentEmpty && (
-
- )}
-
+ {filteredAccounts.map((account) => (
+ accessAccount(e)}
+ onUpdate={(e) => handlePopUpOpen("updateAccount", e)}
+ onDelete={(e) => handlePopUpOpen("deleteAccount", e)}
+ />
+ ))}
+ >
+ )}
+
+
+ {!isLoading && isContentEmpty && (
+
+ )}
+ {Boolean(totalCount) && !isLoading && !isContentEmpty && (
+ setPage(newPage)}
+ onChangePerPage={handlePerPageChange}
+ perPageList={[9, 18, 48, 99]}
+ />
+ )}
+
+ )}
handlePopUpToggle("deleteFolder", isOpen)}
diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamAddAccountModal.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamAddAccountModal.tsx
index 6074e572a..00ef0e1b7 100644
--- a/frontend/src/pages/pam/PamAccountsPage/components/PamAddAccountModal.tsx
+++ b/frontend/src/pages/pam/PamAccountsPage/components/PamAddAccountModal.tsx
@@ -48,6 +48,7 @@ export const PamAddAccountModal = ({
onComplete={(account) => {
if (onComplete) onComplete(account);
onOpenChange(false);
+ setSelectedResource(null);
}}
onBack={() => setSelectedResource(null)}
resourceId={selectedResource.id}