github.com/grafana/pyroscope@v1.18.0/public/app/components/TenantWall.tsx (about) 1 import React, { useEffect, useState } from 'react'; 2 import { useAppDispatch, useAppSelector } from '@pyroscope/redux/hooks'; 3 import TextField from '@pyroscope/ui/Form/TextField'; 4 import { 5 Dialog, 6 DialogBody, 7 DialogFooter, 8 DialogHeader, 9 } from '@pyroscope/ui/Dialog'; 10 import Button from '@pyroscope/ui/Button'; 11 import { 12 checkTenancyIsRequired, 13 selectTenancy, 14 actions, 15 selectTenantID, 16 } from '@pyroscope/redux/reducers/tenant'; 17 18 export function TenantWall({ children }: { children: React.ReactNode }) { 19 const dispatch = useAppDispatch(); 20 const tenancy = useAppSelector(selectTenancy); 21 const currentTenant = useAppSelector(selectTenantID); 22 23 useEffect(() => { 24 void dispatch(checkTenancyIsRequired()); 25 }, [dispatch]); 26 27 // Don't rerender all the children when this component changes 28 // For example, when user wants to change the tenant ID 29 const memoedChildren = React.useMemo(() => children, [children]); 30 31 switch (tenancy) { 32 case 'unknown': 33 case 'loading': { 34 return <></>; 35 } 36 case 'wants_to_change': { 37 return ( 38 <> 39 <SelectTenantIDDialog 40 currentTenantID={currentTenant} 41 onSaved={(tenantID) => { 42 void dispatch(actions.setTenantID(tenantID)); 43 }} 44 /> 45 {memoedChildren} 46 </> 47 ); 48 } 49 case 'needs_tenant_id': { 50 return ( 51 <SelectTenantIDDialog 52 currentTenantID={currentTenant} 53 onSaved={(tenantID) => { 54 void dispatch(actions.setTenantID(tenantID)); 55 }} 56 /> 57 ); 58 } 59 case 'multi_tenant': 60 case 'single_tenant': { 61 return <>{memoedChildren}</>; 62 } 63 } 64 65 return <></>; 66 } 67 68 function SelectTenantIDDialog({ 69 currentTenantID, 70 onSaved, 71 }: { 72 currentTenantID?: string; 73 onSaved: (tenantID: string) => void; 74 }) { 75 const [isDialogOpen] = useState(true); 76 const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => { 77 e.preventDefault(); 78 79 const target = e.target as typeof e.target & { 80 tenantID: { value: string }; 81 }; 82 83 onSaved(target.tenantID.value); 84 }; 85 86 return ( 87 <> 88 <Dialog open={isDialogOpen} aria-labelledby="dialog-header"> 89 <> 90 <DialogHeader> 91 <h3 id="dialog-header">Enter a Tenant ID</h3> 92 </DialogHeader> 93 <form 94 onSubmit={(e) => { 95 void handleFormSubmit(e); 96 }} 97 > 98 <DialogBody> 99 <> 100 <p> 101 Your instance has been detected as a multitenant one. Please 102 enter a Tenant ID (You can change it at any time via the 103 sidebar). 104 </p> 105 <p> 106 Notice that if you migrated from a non-multitenant version, 107 data can be found under Tenant ID {`"anonymous"`}. 108 </p> 109 110 <TextField 111 defaultValue={currentTenantID} 112 label="Tenant ID" 113 required 114 id="tenantID" 115 type="text" 116 autoFocus 117 /> 118 </> 119 </DialogBody> 120 <DialogFooter> 121 <Button type="submit" kind="secondary"> 122 Submit 123 </Button> 124 </DialogFooter> 125 </form> 126 </> 127 </Dialog> 128 </> 129 ); 130 }