@@ -31,6 +31,7 @@ import Button from "@/refresh-components/buttons/Button";
3131import CopyIconButton from "@/refresh-components/buttons/CopyIconButton" ;
3232import Text from "@/refresh-components/texts/Text" ;
3333import { SvgEdit , SvgKey , SvgRefreshCw } from "@opal/icons" ;
34+ import { useCloudSubscription } from "@/hooks/useCloudSubscription" ;
3435
3536function Main ( ) {
3637 const {
@@ -39,6 +40,8 @@ function Main() {
3940 error,
4041 } = useSWR < APIKey [ ] > ( "/api/admin/api-key" , errorHandlingFetcher ) ;
4142
43+ const canCreateKeys = useCloudSubscription ( ) ;
44+
4245 const [ fullApiKey , setFullApiKey ] = useState < string | null > ( null ) ;
4346 const [ keyIsGenerating , setKeyIsGenerating ] = useState ( false ) ;
4447 const [ showCreateUpdateForm , setShowCreateUpdateForm ] = useState ( false ) ;
@@ -70,12 +73,23 @@ function Main() {
7073 const introSection = (
7174 < div className = "flex flex-col items-start gap-4" >
7275 < Text as = "p" >
73- API Keys allow you to access Onyx APIs programmatically. Click the
74- button below to generate a new API Key.
76+ API Keys allow you to access Onyx APIs programmatically.
77+ { canCreateKeys
78+ ? " Click the button below to generate a new API Key."
79+ : "" }
7580 </ Text >
76- < CreateButton onClick = { ( ) => setShowCreateUpdateForm ( true ) } >
77- Create API Key
78- </ CreateButton >
81+ { canCreateKeys ? (
82+ < CreateButton onClick = { ( ) => setShowCreateUpdateForm ( true ) } >
83+ Create API Key
84+ </ CreateButton >
85+ ) : (
86+ < div className = "flex flex-col gap-2 rounded-lg bg-background-tint-02 p-4" >
87+ < Text as = "p" text04 >
88+ This feature requires an active paid subscription.
89+ </ Text >
90+ < Button href = "/admin/billing" > Upgrade Plan</ Button >
91+ </ div >
92+ ) }
7993 </ div >
8094 ) ;
8195
@@ -109,7 +123,7 @@ function Main() {
109123 title = "New API Key"
110124 icon = { SvgKey }
111125 onClose = { ( ) => setFullApiKey ( null ) }
112- description = "Make sure you copy your new API key. You won’ t be able to see this key again."
126+ description = "Make sure you copy your new API key. You won' t be able to see this key again."
113127 />
114128 < Modal . Body >
115129 < Text as = "p" className = "break-all flex-1" >
@@ -124,88 +138,94 @@ function Main() {
124138
125139 { introSection }
126140
127- < Separator />
128-
129- < Title className = "mt-6" > Existing API Keys</ Title >
130- < Table className = "overflow-visible" >
131- < TableHeader >
132- < TableRow >
133- < TableHead > Name</ TableHead >
134- < TableHead > API Key</ TableHead >
135- < TableHead > Role</ TableHead >
136- < TableHead > Regenerate</ TableHead >
137- < TableHead > Delete</ TableHead >
138- </ TableRow >
139- </ TableHeader >
140- < TableBody >
141- { filteredApiKeys . map ( ( apiKey ) => (
142- < TableRow key = { apiKey . api_key_id } >
143- < TableCell >
144- < Button
145- internal
146- onClick = { ( ) => handleEdit ( apiKey ) }
147- leftIcon = { SvgEdit }
148- >
149- { apiKey . api_key_name || < i > null</ i > }
150- </ Button >
151- </ TableCell >
152- < TableCell className = "max-w-64" >
153- { apiKey . api_key_display }
154- </ TableCell >
155- < TableCell className = "max-w-64" >
156- { apiKey . api_key_role . toUpperCase ( ) }
157- </ TableCell >
158- < TableCell >
159- < Button
160- internal
161- leftIcon = { SvgRefreshCw }
162- onClick = { async ( ) => {
163- setKeyIsGenerating ( true ) ;
164- const response = await regenerateApiKey ( apiKey ) ;
165- setKeyIsGenerating ( false ) ;
166- if ( ! response . ok ) {
167- const errorMsg = await response . text ( ) ;
168- toast . error ( `Failed to regenerate API Key: ${ errorMsg } ` ) ;
169- return ;
170- }
171- const newKey = ( await response . json ( ) ) as APIKey ;
172- setFullApiKey ( newKey . api_key ) ;
173- mutate ( "/api/admin/api-key" ) ;
174- } }
175- >
176- Refresh
177- </ Button >
178- </ TableCell >
179- < TableCell >
180- < DeleteButton
181- onClick = { async ( ) => {
182- const response = await deleteApiKey ( apiKey . api_key_id ) ;
183- if ( ! response . ok ) {
184- const errorMsg = await response . text ( ) ;
185- toast . error ( `Failed to delete API Key: ${ errorMsg } ` ) ;
186- return ;
187- }
188- mutate ( "/api/admin/api-key" ) ;
189- } }
190- />
191- </ TableCell >
192- </ TableRow >
193- ) ) }
194- </ TableBody >
195- </ Table >
196-
197- { showCreateUpdateForm && (
198- < OnyxApiKeyForm
199- onCreateApiKey = { ( apiKey ) => {
200- setFullApiKey ( apiKey . api_key ) ;
201- } }
202- onClose = { ( ) => {
203- setShowCreateUpdateForm ( false ) ;
204- setSelectedApiKey ( undefined ) ;
205- mutate ( "/api/admin/api-key" ) ;
206- } }
207- apiKey = { selectedApiKey }
208- />
141+ { canCreateKeys && (
142+ < >
143+ < Separator />
144+
145+ < Title className = "mt-6" > Existing API Keys</ Title >
146+ < Table className = "overflow-visible" >
147+ < TableHeader >
148+ < TableRow >
149+ < TableHead > Name</ TableHead >
150+ < TableHead > API Key</ TableHead >
151+ < TableHead > Role</ TableHead >
152+ < TableHead > Regenerate</ TableHead >
153+ < TableHead > Delete</ TableHead >
154+ </ TableRow >
155+ </ TableHeader >
156+ < TableBody >
157+ { filteredApiKeys . map ( ( apiKey ) => (
158+ < TableRow key = { apiKey . api_key_id } >
159+ < TableCell >
160+ < Button
161+ internal
162+ onClick = { ( ) => handleEdit ( apiKey ) }
163+ leftIcon = { SvgEdit }
164+ >
165+ { apiKey . api_key_name || < i > null</ i > }
166+ </ Button >
167+ </ TableCell >
168+ < TableCell className = "max-w-64" >
169+ { apiKey . api_key_display }
170+ </ TableCell >
171+ < TableCell className = "max-w-64" >
172+ { apiKey . api_key_role . toUpperCase ( ) }
173+ </ TableCell >
174+ < TableCell >
175+ < Button
176+ internal
177+ leftIcon = { SvgRefreshCw }
178+ onClick = { async ( ) => {
179+ setKeyIsGenerating ( true ) ;
180+ const response = await regenerateApiKey ( apiKey ) ;
181+ setKeyIsGenerating ( false ) ;
182+ if ( ! response . ok ) {
183+ const errorMsg = await response . text ( ) ;
184+ toast . error (
185+ `Failed to regenerate API Key: ${ errorMsg } `
186+ ) ;
187+ return ;
188+ }
189+ const newKey = ( await response . json ( ) ) as APIKey ;
190+ setFullApiKey ( newKey . api_key ) ;
191+ mutate ( "/api/admin/api-key" ) ;
192+ } }
193+ >
194+ Refresh
195+ </ Button >
196+ </ TableCell >
197+ < TableCell >
198+ < DeleteButton
199+ onClick = { async ( ) => {
200+ const response = await deleteApiKey ( apiKey . api_key_id ) ;
201+ if ( ! response . ok ) {
202+ const errorMsg = await response . text ( ) ;
203+ toast . error ( `Failed to delete API Key: ${ errorMsg } ` ) ;
204+ return ;
205+ }
206+ mutate ( "/api/admin/api-key" ) ;
207+ } }
208+ />
209+ </ TableCell >
210+ </ TableRow >
211+ ) ) }
212+ </ TableBody >
213+ </ Table >
214+
215+ { showCreateUpdateForm && (
216+ < OnyxApiKeyForm
217+ onCreateApiKey = { ( apiKey ) => {
218+ setFullApiKey ( apiKey . api_key ) ;
219+ } }
220+ onClose = { ( ) => {
221+ setShowCreateUpdateForm ( false ) ;
222+ setSelectedApiKey ( undefined ) ;
223+ mutate ( "/api/admin/api-key" ) ;
224+ } }
225+ apiKey = { selectedApiKey }
226+ />
227+ ) }
228+ </ >
209229 ) }
210230 </ >
211231 ) ;
0 commit comments