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  }