Skip to content

Commit ff7f1fb

Browse files
authored
Merge pull request #6179 from bcgov/chore/6168
refactor(6168): improve team API accounts page
2 parents 170f446 + 2d03fa0 commit ff7f1fb

File tree

2 files changed

+88
-99
lines changed

2 files changed

+88
-99
lines changed

app/app/team-api-accounts/page.tsx

Lines changed: 86 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
'use client';
22

3-
import { Table, Badge, Button } from '@mantine/core';
3+
import { Badge, Button } from '@mantine/core';
44
import { useQuery } from '@tanstack/react-query';
55
import _compact from 'lodash-es/compact';
66
import _get from 'lodash-es/get';
7-
import { JSX, ReactNode } from 'react';
7+
import { useMemo } from 'react';
88
import DataTable from '@/components/generic/data-table/DataTable';
9+
import type { ColumnDefinition } from '@/components/generic/data-table/DataTable';
910
import { GlobalRole } from '@/constants';
1011
import createClientPage from '@/core/client-page';
1112
import { listKeycloakTeamApiAccounts } from '@/services/backend/keycloak';
@@ -21,83 +22,10 @@ interface TeamApiAccount {
2122
secret: string;
2223
}
2324

24-
interface ColumnDef {
25-
label?: string;
26-
value: string;
27-
cellProcessor: (account: TeamApiAccount, attr: string) => React.ReactNode;
28-
}
29-
3025
const TeamApiAccountsPage = createClientPage({
3126
roles: [GlobalRole.User],
3227
});
3328
export default TeamApiAccountsPage(({ session }) => {
34-
const teamApiAccountData: TeamApiAccount[] = [];
35-
const tableColumns: ColumnDef[] = [
36-
{
37-
label: 'Name',
38-
value: 'name',
39-
cellProcessor: (account, attr) => (
40-
<span className="whitespace-nowrap">
41-
{account.name}{' '}
42-
<Badge color="green" radius="sm" className="ml-1">
43-
Active
44-
</Badge>
45-
</span>
46-
),
47-
},
48-
{
49-
label: 'Roles',
50-
value: 'roles',
51-
cellProcessor: (account, attr) => (
52-
<>
53-
{account.roles.map((role) => (
54-
<Badge key={role} color="gray" radius="sm" className="mr-1">
55-
{role}
56-
</Badge>
57-
))}
58-
</>
59-
),
60-
},
61-
{
62-
label: '',
63-
value: 'actionButtons',
64-
cellProcessor: (account, attr) => (
65-
<>
66-
<Button
67-
className="mr-1"
68-
variant="outline"
69-
onClick={async () => {
70-
await openViewAccountModal({
71-
clientUid: account.id,
72-
clientId: account.clientId,
73-
clientSecret: account.secret,
74-
name: account.name,
75-
roles: account.roles,
76-
});
77-
}}
78-
>
79-
View
80-
</Button>
81-
{session?.isAdmin && (
82-
<Button
83-
variant="outline"
84-
onClick={async () => {
85-
await openManageAccountModal({
86-
clientUid: account.id,
87-
roles: account.roles,
88-
name: account.name ?? '',
89-
});
90-
await refetchApiAccounts();
91-
}}
92-
>
93-
Manage
94-
</Button>
95-
)}
96-
</>
97-
),
98-
},
99-
];
100-
10129
const {
10230
data: apiAccounts,
10331
isLoading: isApiAccountsLoading,
@@ -109,40 +37,101 @@ export default TeamApiAccountsPage(({ session }) => {
10937
queryFn: () => listKeycloakTeamApiAccounts(),
11038
});
11139

112-
if (isApiAccountsLoading) {
113-
return null;
114-
}
40+
const { data: tableData, columns: tableColumns } = useMemo(() => {
41+
if (!apiAccounts) return { data: [], columns: [] };
11542

116-
let rows: ReactNode = null;
117-
if (!apiAccounts || apiAccounts.length === 0) {
118-
const message = session?.isAdmin ? 'No team API accounts found.' : 'You are not assigned to any team API accounts.';
43+
const _columns: ColumnDefinition<TeamApiAccount>[] = [
44+
{
45+
label: 'Name',
46+
value: 'name',
47+
cellProcessor: (account, attr) => (
48+
<span className="whitespace-nowrap">
49+
{account.name}{' '}
50+
<Badge color="green" radius="sm" className="ml-1">
51+
Active
52+
</Badge>
53+
</span>
54+
),
55+
},
56+
{
57+
label: 'Roles',
58+
value: 'roles',
59+
cellProcessor: (account, attr) => (
60+
<>
61+
{account.roles.map((role) => (
62+
<Badge key={role} color="gray" radius="sm" className="mr-1">
63+
{role}
64+
</Badge>
65+
))}
66+
</>
67+
),
68+
},
69+
{
70+
label: '',
71+
value: 'actionButtons',
72+
cellProcessor: (account, attr) => (
73+
<>
74+
<Button
75+
className="mr-1"
76+
variant="outline"
77+
onClick={async () => {
78+
await openViewAccountModal({
79+
clientUid: account.id,
80+
clientId: account.clientId,
81+
clientSecret: account.secret,
82+
name: account.name,
83+
roles: account.roles,
84+
});
85+
}}
86+
>
87+
View
88+
</Button>
89+
{session?.isAdmin && (
90+
<Button
91+
variant="outline"
92+
onClick={async () => {
93+
await openManageAccountModal({
94+
clientUid: account.id,
95+
roles: account.roles,
96+
name: account.name ?? '',
97+
});
98+
await refetchApiAccounts();
99+
}}
100+
>
101+
Manage
102+
</Button>
103+
)}
104+
</>
105+
),
106+
},
107+
];
119108

120-
rows = (
121-
<Table.Tr>
122-
<Table.Td colSpan={3}>{message}</Table.Td>
123-
</Table.Tr>
124-
);
125-
} else {
126-
(apiAccounts ?? []).forEach((account) => {
109+
const _data: TeamApiAccount[] = (apiAccounts ?? []).map((account) => {
127110
const rolesMapper = account.protocolMappers?.find((mapper) => mapper.name === 'roles');
128111
const rolesStr = _get(rolesMapper, ['config', 'claim.value'], '');
129112

130-
teamApiAccountData.push({
131-
name: account.name!,
113+
return {
114+
name: account.name ?? '',
132115
roles: _compact(rolesStr.split(',')),
133-
id: account.id!,
134-
clientId: account.clientId!,
135-
secret: account.secret!,
136-
});
116+
id: account.id ?? '',
117+
clientId: account.clientId ?? '',
118+
secret: account.secret ?? '',
119+
};
137120
});
121+
122+
return { data: _data, columns: _columns };
123+
}, [session, apiAccounts]);
124+
125+
if (isApiAccountsLoading) {
126+
return null;
138127
}
139128

140129
return (
141130
<div className="pt-5">
142-
<h1 className="text-xl lg:text-2xl 2xl:text-4xl font-semibold leading-7 text-gray-900 pb-2">Team API Accounts</h1>
131+
<h1 className="text-xl lg:text-2xl 2xl:text-4xl font-semibold leading-7 text-gray-900">Team API Accounts</h1>
143132

144133
{session?.isAdmin && (
145-
<div className="text-right mb-11">
134+
<div className="text-right mb-2">
146135
<Button
147136
color="blue"
148137
onClick={async () => {
@@ -154,7 +143,7 @@ export default TeamApiAccountsPage(({ session }) => {
154143
</Button>
155144
</div>
156145
)}
157-
<DataTable<TeamApiAccount> data={teamApiAccountData} columns={tableColumns} />
146+
<DataTable<TeamApiAccount> data={tableData} columns={tableColumns} />
158147
</div>
159148
);
160149
});

app/components/generic/data-table/DataTable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import _startCase from 'lodash-es/startCase';
1414
import { useEffect, useMemo, useState } from 'react';
1515
import Pagination from './Pagination';
1616

17-
interface ColumnDefinition<TData> {
17+
export interface ColumnDefinition<TData> {
1818
label?: string | null;
1919
value: string;
2020
cellProcessor?: (item: TData, attribute: string) => React.ReactNode;
@@ -104,7 +104,7 @@ export default function DataTable<TData extends object>({
104104

105105
return (
106106
<>
107-
<div className="border border-gray-200 overflow-hidden mt-5 rounded-md">
107+
<div className="border border-gray-200 overflow-hidden rounded-md">
108108
<div className="overflow-x-auto">
109109
<table className="w-full text-sm border-collapse">
110110
<thead>

0 commit comments

Comments
 (0)