Skip to content

Commit 9be1d2f

Browse files
authored
Add update forms for role management (#4558)
* update menu * start add role management routes * add router tabs * update avatar ui * add accounts, groups, and fix tabs router * add roles * add permissions and badge copy * update icon * update group member ui * update permissions icon * add delete account * update table * delete group * delete roles * delete permissions * fix delete labels * separate global and object permissions * fix error in tabs * add idientifier * 🔧 * fix avatar schema load * fix account constant * fix action attribute * name queries * rename navigation * use generic account * fix test when displaying more count * add test for read views * add description in color display for accounts * prevent delete global permissions * update permissions icons * fix test url * fix router * lint * create account * update locator for variable member order * update locators for object permissions * udpate test * update locator * update locator * update ignore * add custom object permission form in object form * add role form * add group form * add account form * fix delete functions * remove log * add on cancel on each form * remove placeholder * fix controlled form re render * update account form * update group form * update role form * update object permissions * update table for actions * add custom form for roles * start fix edit form for accounts * rename * rename * start add group update form * start update role form * start update object permissions form * update edit forms * fix update mutation for relationships many * add again submodule * update tests locators * type update * update locators * update types * update locators * update locators * fix locator * fix proposed changes table * update permission form * update namespace selection for nodes * fix test * fix group form slide over * update permissions rows and action option in form * fix locator
1 parent 9381508 commit 9be1d2f

25 files changed

+492
-250
lines changed

frontend/app/src/components/form/object-form.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { NodeWithProfileForm } from "@/components/form/node-with-profile-form";
55
import {
66
ACCOUNT_GROUP_OBJECT,
77
ACCOUNT_OBJECT,
8+
ACCOUNT_ROLE_OBJECT,
89
NUMBER_POOL_OBJECT,
910
OBJECT_PERMISSION_OBJECT,
1011
READONLY_REPOSITORY_KIND,
@@ -16,6 +17,7 @@ import LoadingScreen from "@/screens/loading-screen/loading-screen";
1617
import { NumberPoolForm } from "@/screens/resource-manager/number-pool-form";
1718
import { AccountForm } from "@/screens/role-management/account-form";
1819
import { AccountGroupForm } from "@/screens/role-management/account-group-form";
20+
import { AccountRoleForm } from "@/screens/role-management/account-role-form";
1921
import { ObjectPermissionForm } from "@/screens/role-management/object-permissions-form";
2022
import { AttributeType, RelationshipType } from "@/utils/getObjectItemDisplayValue";
2123
import { Suspense, lazy } from "react";
@@ -62,16 +64,20 @@ const ObjectForm = ({ kind, currentProfiles, ...props }: ObjectFormProps) => {
6264
return <NumberPoolForm {...props} />;
6365
}
6466

65-
if (kind === OBJECT_PERMISSION_OBJECT) {
66-
return <ObjectPermissionForm {...props} />;
67+
if (kind === ACCOUNT_OBJECT) {
68+
return <AccountForm {...props} />;
6769
}
6870

6971
if (kind === ACCOUNT_GROUP_OBJECT) {
7072
return <AccountGroupForm {...props} />;
7173
}
7274

73-
if (kind === ACCOUNT_OBJECT) {
74-
return <AccountForm {...props} />;
75+
if (kind === ACCOUNT_ROLE_OBJECT) {
76+
return <AccountRoleForm {...props} />;
77+
}
78+
79+
if (kind === OBJECT_PERMISSION_OBJECT) {
80+
return <ObjectPermissionForm {...props} />;
7581
}
7682

7783
if (isGeneric) {

frontend/app/src/components/form/utils/getFieldDefaultValue.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export const getCurrentFieldValue = (
4242
if (!objectData) return null;
4343

4444
const currentField = objectData[fieldName];
45+
4546
if (!currentField) return null;
4647

4748
if (currentField.is_default || currentField.is_from_profile) {

frontend/app/src/components/form/utils/mutations/getCreateMutationFromFormData.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ export const getCreateMutationFromFormDataOnly = (
4646

4747
if (data.source?.type === "user") {
4848
const fieldValue = data.value === "" ? null : data.value;
49+
4950
return {
5051
...acc,
51-
[name]: { value: fieldValue },
52+
[name]: Array.isArray(fieldValue) ? fieldValue : { value: fieldValue },
5253
};
5354
}
5455

Lines changed: 87 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,39 @@
1-
import { Button } from "@/components/buttons/button-primitive";
1+
import { ButtonWithTooltip } from "@/components/buttons/button-primitive";
22
import { useAuth } from "@/hooks/useAuth";
33
import NoDataFound from "@/screens/errors/no-data-found";
44
import { classNames } from "@/utils/common";
55
import { Icon } from "@iconify-icon/react";
66
import { Link } from "react-router-dom";
77

8+
import { ReactNode } from "react";
9+
import {
10+
DropdownMenu,
11+
DropdownMenuContent,
12+
DropdownMenuItem,
13+
DropdownMenuTrigger,
14+
} from "../ui/dropdown-menu";
15+
16+
export type tRowValue = {
17+
value: unknown;
18+
display: ReactNode;
19+
};
20+
821
export type tColumn = {
922
name: string;
1023
label: string;
1124
};
1225

1326
export type tRow = {
1427
link?: string;
15-
values: any;
28+
values: Record<string, string | number | tRowValue>;
1629
};
1730

1831
type TableProps = {
1932
columns: tColumn[];
2033
rows: tRow[];
2134
constructLink?: Function;
2235
onDelete?: (row: tRow) => void;
23-
onUpdate?: Function;
36+
onUpdate?: (row: tRow) => void;
2437
className?: string;
2538
};
2639

@@ -56,58 +69,87 @@ export const Table = ({ columns, rows, onDelete, onUpdate, className }: TablePro
5669
)}
5770
data-cy="object-table-row"
5871
>
59-
{columns.map((column, index) => (
60-
<td key={index} className="p-0">
61-
{row.link && (
62-
<Link
63-
className="whitespace-wrap px-2 py-1 text-xs text-gray-900 flex items-center"
64-
to={row.link}
65-
>
66-
{row.values[column.name] ?? "-"}
67-
</Link>
68-
)}
69-
70-
{!row.link && (
71-
<div className="whitespace-wrap px-2 py-1 text-xs text-gray-900 flex items-center">
72-
{row.values[column.name] ?? "-"}
73-
</div>
74-
)}
75-
</td>
76-
))}
72+
{columns.map((column, index) => {
73+
return (
74+
<td key={index} className="p-0">
75+
{row.link && (
76+
<Link
77+
className="whitespace-wrap px-2 py-1 text-xs text-gray-900 flex items-center"
78+
to={row.link}
79+
>
80+
{renderRowValue(row.values[column.name])}
81+
</Link>
82+
)}
83+
84+
{!row.link && (
85+
<div className="whitespace-wrap px-2 py-1 text-xs text-gray-900 flex items-center">
86+
{renderRowValue(row.values[column.name])}
87+
</div>
88+
)}
89+
</td>
90+
);
91+
})}
7792

7893
{(onUpdate || onDelete) && (
7994
<td className="text-right">
80-
{onUpdate && (
81-
<Button
82-
variant="ghost"
83-
size="icon"
84-
disabled={!auth?.permissions?.write}
85-
onClick={() => onUpdate(row)}
86-
data-testid="update-row-button"
87-
>
88-
<Icon icon="mdi:pencil" className="text-custom-blue-500" />
89-
</Button>
90-
)}
91-
92-
{onDelete && (
93-
<Button
94-
variant="ghost"
95-
size="icon"
96-
disabled={!auth?.permissions?.write}
97-
onClick={() => onDelete(row)}
98-
data-testid="delete-row-button"
99-
>
100-
<Icon icon="mdi:trash-outline" className="text-red-500" />
101-
</Button>
102-
)}
95+
<DropdownMenu>
96+
<DropdownMenuTrigger asChild>
97+
<ButtonWithTooltip
98+
tooltipContent="Actions"
99+
tooltipEnabled
100+
variant="ghost"
101+
size="square"
102+
className="p-4"
103+
data-testid="actions-row-button"
104+
>
105+
<Icon icon="mdi:dots-vertical" className="" />
106+
</ButtonWithTooltip>
107+
</DropdownMenuTrigger>
108+
109+
<DropdownMenuContent align="end">
110+
{onUpdate && (
111+
<DropdownMenuItem
112+
onClick={() => onUpdate(row)}
113+
disabled={!auth?.permissions?.write}
114+
data-testid="update-row-button"
115+
>
116+
<Icon icon="mdi:pencil" className="text-custom-blue-500" />
117+
Edit
118+
</DropdownMenuItem>
119+
)}
120+
121+
{onDelete && (
122+
<DropdownMenuItem
123+
onClick={() => onDelete(row)}
124+
disabled={!auth?.permissions?.write}
125+
data-testid="delete-row-button"
126+
>
127+
<Icon icon="mdi:trash-outline" className="text-red-500" />
128+
Delete
129+
</DropdownMenuItem>
130+
)}
131+
</DropdownMenuContent>
132+
</DropdownMenu>
103133
</td>
104134
)}
105135
</tr>
106136
))}
107137
</tbody>
108138
</table>
109139

110-
{!rows?.length && <NoDataFound message="No items" className="m-auto w-full" />}
140+
{!rows?.length && <NoDataFound message="No items" />}
111141
</>
112142
);
113143
};
144+
145+
const renderRowValue = (data: string | number | tRowValue): ReactNode => {
146+
if (!data) return "-";
147+
148+
if (typeof data === "string" || typeof data === "number") return data;
149+
150+
if ("display" in data) return data.display as ReactNode;
151+
152+
if ("value" in data) return data.value as ReactNode;
153+
154+
return "-";
155+
};

frontend/app/src/graphql/queries/role-management/getAccounts.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ export const GET_ROLE_MANAGEMENT_ACCOUNTS = gql`
77
edges {
88
node {
99
id
10+
name {
11+
value
12+
}
1013
description {
1114
value
1215
}
13-
display_label
1416
account_type {
1517
value
1618
}
@@ -19,6 +21,15 @@ export const GET_ROLE_MANAGEMENT_ACCOUNTS = gql`
1921
color
2022
description
2123
}
24+
member_of_groups {
25+
count
26+
edges {
27+
node {
28+
id
29+
display_label
30+
}
31+
}
32+
}
2233
}
2334
}
2435
}

frontend/app/src/graphql/queries/role-management/getGroups.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ export const GET_ROLE_MANAGEMENT_GROUPS = gql`
66
edges {
77
node {
88
id
9-
display_label
9+
name {
10+
value
11+
}
1012
description {
1113
value
1214
}
@@ -16,6 +18,16 @@ export const GET_ROLE_MANAGEMENT_GROUPS = gql`
1618
members {
1719
edges {
1820
node {
21+
id
22+
display_label
23+
}
24+
}
25+
}
26+
roles {
27+
count
28+
edges {
29+
node {
30+
id
1931
display_label
2032
}
2133
}

frontend/app/src/graphql/queries/role-management/getObjectPermissions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ export const GET_ROLE_MANAGEMENT_OBJECT_PERMISSIONS = gql`
2424
}
2525
roles {
2626
count
27+
edges {
28+
node {
29+
id
30+
}
31+
}
2732
}
2833
identifier {
2934
value

frontend/app/src/graphql/queries/role-management/getRoles.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,24 @@ export const GET_ROLE_MANAGEMENT_ROLES = gql`
66
edges {
77
node {
88
id
9-
display_label
9+
name {
10+
value
11+
}
1012
groups {
1113
count
14+
edges {
15+
node {
16+
id
17+
}
18+
}
1219
}
1320
permissions {
1421
count
22+
edges {
23+
node {
24+
id
25+
}
26+
}
1527
}
1628
}
1729
}

frontend/app/src/screens/object-items/object-items-paginated.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ export default function ObjectItems({
6262

6363
const result = data && schema?.kind ? (data[kindFilter?.value || schema?.kind] ?? {}) : {};
6464

65-
const { count = "...", edges } = result;
65+
const { count = "...", edges, permissions } = result;
66+
console.log("permissions: ", permissions);
6667

6768
useTitle(`${schema.label || schema.name} list`);
6869

@@ -99,6 +100,12 @@ export default function ObjectItems({
99100
return <ErrorScreen message="Something went wrong when fetching list." />;
100101
}
101102

103+
const currentPermission = permissions?.edges[0]?.node;
104+
105+
if (currentPermission?.view !== "ALLOW") {
106+
// return <UnauthorizedScreen />;
107+
}
108+
102109
return (
103110
<>
104111
<div

0 commit comments

Comments
 (0)