@@ -7,23 +7,19 @@ import {
77 NewAlert ,
88 NewButton ,
99 Modal ,
10- NewTable ,
1110 NewIcon ,
1211 NewTextInput ,
13- Heading ,
1412 CodeBox ,
1513} from "@thunderstore/cyberstorm" ;
16- import { TableSort } from "@thunderstore/cyberstorm/src/newComponents/Table/Table" ;
1714import {
18- type RequestConfig ,
1915 teamAddServiceAccount ,
2016 type TeamServiceAccountAddRequestData ,
2117} from "@thunderstore/thunderstore-api" ;
2218
2319import { type OutletContextShape } from "app/root" ;
2420import { makeTeamSettingsTabLoader } from "cyberstorm/utils/dapperClientLoaders" ;
2521import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm" ;
26- import { ServiceAccountRemoveModal } from "./ServiceAccountRemoveModal " ;
22+ import { ServiceAccountsTable } from "./ServiceAccountsTable " ;
2723import "./ServiceAccounts.css" ;
2824
2925export const clientLoader = makeTeamSettingsTabLoader (
@@ -36,81 +32,30 @@ export function HydrateFallback() {
3632 return < div style = { { padding : "32px" } } > Loading...</ div > ;
3733}
3834
39- const serviceAccountColumns = [
40- { value : "Nickname" , disableSort : false } ,
41- { value : "Last Used" , disableSort : false } ,
42- { value : "Actions" , disableSort : true } ,
43- ] ;
44-
4535export default function ServiceAccounts ( ) {
4636 const { teamName, serviceAccounts } = useLoaderData < typeof clientLoader > ( ) ;
47- const outletContext = useOutletContext ( ) as OutletContextShape ;
48-
4937 const revalidator = useRevalidator ( ) ;
5038
51- const currentUserTeam = outletContext . currentUser ?. teams_full ?. find (
52- ( team ) => team . name === teamName
53- ) ;
54- const isOwner = currentUserTeam ?. role === "owner" ;
55-
5639 async function serviceAccountRevalidate ( ) {
5740 revalidator . revalidate ( ) ;
5841 }
5942
60- const tableData = serviceAccounts . map ( ( serviceAccount ) => {
61- return [
62- {
63- value : (
64- < p className = "team-service-accounts__nickname" >
65- { serviceAccount . name }
66- </ p >
67- ) ,
68- sortValue : serviceAccount . name ,
69- } ,
70- {
71- value : (
72- < p className = "team-service-accounts__last-used" >
73- { serviceAccount . last_used ?? "Never" }
74- </ p >
75- ) ,
76- sortValue : serviceAccount . last_used ?? "0" ,
77- } ,
78- {
79- value : (
80- < ServiceAccountRemoveModal
81- key = { serviceAccount . identifier }
82- serviceAccount = { serviceAccount }
83- teamName = { teamName }
84- outletContext = { outletContext }
85- revalidate = { serviceAccountRevalidate }
86- />
87- ) ,
88- sortValue : 0 ,
89- } ,
90- ] ;
91- } ) ;
92-
9343 return (
9444 < div className = "settings-items" >
9545 < div className = "settings-items__item" >
9646 < div className = "settings-items__meta" >
9747 < p className = "settings-items__title" > Service accounts</ p >
9848 < p className = "settings-items__description" > Your loyal servants</ p >
99- { isOwner && (
100- < AddServiceAccountForm
101- teamName = { teamName }
102- config = { outletContext . requestConfig }
103- serviceAccountRevalidate = { serviceAccountRevalidate }
104- />
105- ) }
49+ < AddServiceAccountForm
50+ teamName = { teamName }
51+ serviceAccountRevalidate = { serviceAccountRevalidate }
52+ />
10653 </ div >
10754 < div className = "settings-items__content" >
108- < NewTable
109- titleRowContent = { < Heading csLevel = "3" > Service Accounts</ Heading > }
110- headers = { serviceAccountColumns }
111- rows = { tableData }
112- sortByHeader = { 1 }
113- sortDirection = { TableSort . ASC }
55+ < ServiceAccountsTable
56+ serviceAccounts = { serviceAccounts }
57+ serviceAccountRevalidate = { serviceAccountRevalidate }
58+ teamName = { teamName }
11459 />
11560 </ div >
11661 </ div >
@@ -120,16 +65,24 @@ export default function ServiceAccounts() {
12065
12166function AddServiceAccountForm ( props : {
12267 teamName : string ;
123- config : ( ) => RequestConfig ;
124- serviceAccountRevalidate ?: ( ) => void ;
68+ serviceAccountRevalidate : ( ) => void ;
12569} ) {
70+ const outletContext = useOutletContext ( ) as OutletContextShape ;
12671 const [ open , setOpen ] = useState ( false ) ;
12772 const [ serviceAccountAdded , setServiceAccountAdded ] = useState ( false ) ;
12873 const [ addedServiceAccountToken , setAddedServiceAccountToken ] = useState ( "" ) ;
12974 const [ addedServiceAccountNickname , setAddedServiceAccountNickname ] =
13075 useState ( "" ) ;
13176 const [ error , setError ] = useState < string | null > ( null ) ;
13277
78+ const currentUserTeam = outletContext . currentUser ?. teams_full ?. find (
79+ ( team ) => team . name === props . teamName
80+ ) ;
81+
82+ if ( currentUserTeam ?. role !== "owner" ) {
83+ return null ;
84+ }
85+
13386 function onSuccess (
13487 result : Awaited < ReturnType < typeof teamAddServiceAccount > >
13588 ) {
@@ -161,7 +114,7 @@ function AddServiceAccountForm(props: {
161114
162115 async function submitor ( data : typeof formInputs ) : Promise < SubmitorOutput > {
163116 return await teamAddServiceAccount ( {
164- config : props . config ,
117+ config : outletContext . requestConfig ,
165118 params : { team_name : props . teamName } ,
166119 queryParams : { } ,
167120 data : { nickname : data . nickname . trim ( ) } ,
@@ -188,7 +141,7 @@ function AddServiceAccountForm(props: {
188141 // Refresh the service accounts list to show the newly created account
189142 // TODO: When API returns identifier in response, we can append the new
190143 // service account to the list instead of refreshing from backend
191- props . serviceAccountRevalidate ?. ( ) ;
144+ props . serviceAccountRevalidate ( ) ;
192145 } ,
193146 onSubmitError : ( error ) => {
194147 const message = `Error occurred: ${ error . message || "Unknown error" } ` ;
0 commit comments