github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/pages/adhoc/AdhocDiff.tsx (about)

     1  import React, { useEffect, useState } from 'react';
     2  import 'react-dom';
     3  import { Maybe } from '@webapp/util/fp';
     4  import { useAppDispatch, useAppSelector } from '@webapp/redux/hooks';
     5  import Box from '@webapp/ui/Box';
     6  import { FlamegraphRenderer } from '@pyroscope/flamegraph/src/FlamegraphRenderer';
     7  import { Profile } from '@pyroscope/models/src';
     8  import FileList from '@webapp/components/FileList';
     9  import useExportToFlamegraphDotCom from '@webapp/components/exportToFlamegraphDotCom.hook';
    10  import ExportData from '@webapp/components/ExportData';
    11  import {
    12    fetchAllProfiles,
    13    fetchDiffProfile,
    14    fetchProfile,
    15    selectedSelectedProfileId,
    16    selectProfileId,
    17    selectShared,
    18    selectDiffProfile,
    19    uploadFile,
    20  } from '@webapp/redux/reducers/adhoc';
    21  import useColorMode from '@webapp/hooks/colorMode.hook';
    22  import { Tabs, Tab, TabPanel } from '@webapp/ui/Tabs';
    23  import adhocStyles from './Adhoc.module.scss';
    24  import adhocComparisonStyles from './AdhocComparison.module.scss';
    25  import FileUploader from './components/FileUploader';
    26  
    27  function AdhocDiff() {
    28    const dispatch = useAppDispatch();
    29    const leftProfileId = useAppSelector(selectProfileId('left'));
    30    const rightProfileId = useAppSelector(selectProfileId('right'));
    31    useColorMode();
    32    const selectedProfileIdLeft = useAppSelector(
    33      selectedSelectedProfileId('left')
    34    );
    35    const selectedProfileIdRight = useAppSelector(
    36      selectedSelectedProfileId('right')
    37    );
    38    const { profilesList } = useAppSelector(selectShared);
    39    const diffProfile = useAppSelector(selectDiffProfile);
    40    const exportToFlamegraphDotComFn = useExportToFlamegraphDotCom(
    41      diffProfile.unwrapOr(undefined)
    42    );
    43    const [tabIndexLeft, setTabIndexLeft] = useState(0);
    44    const [tabIndexRight, setTabIndexRight] = useState(0);
    45  
    46    useEffect(() => {
    47      dispatch(fetchAllProfiles());
    48    }, [dispatch]);
    49  
    50    useEffect(() => {
    51      if (leftProfileId.isJust && rightProfileId.isJust) {
    52        dispatch(
    53          fetchDiffProfile({
    54            leftId: leftProfileId.value,
    55            rightId: rightProfileId.value,
    56          })
    57        );
    58      }
    59    }, [
    60      dispatch,
    61      leftProfileId.unwrapOr(undefined),
    62      rightProfileId.unwrapOr(undefined),
    63    ]);
    64  
    65    const flamegraph = (
    66      profile: Maybe<Profile>,
    67      exportToFn: ReturnType<typeof useExportToFlamegraphDotCom>
    68    ) => {
    69      if (profile.isNothing) {
    70        return <></>;
    71      }
    72  
    73      return (
    74        <FlamegraphRenderer
    75          profile={profile.value}
    76          showCredit={false}
    77          panesOrientation="vertical"
    78          ExportData={
    79            <ExportData
    80              flamebearer={profile.value}
    81              exportJSON
    82              exportFlamegraphDotCom
    83              exportFlamegraphDotComFn={exportToFn}
    84            />
    85          }
    86        />
    87      );
    88    };
    89  
    90    return (
    91      <div>
    92        <div className="main-wrapper">
    93          <div
    94            className="comparison-container"
    95            data-testid="comparison-container"
    96          >
    97            <Box className={adhocComparisonStyles.comparisonPane}>
    98              <Tabs
    99                value={tabIndexLeft}
   100                onChange={(e, value) => setTabIndexLeft(value)}
   101              >
   102                <Tab label="Upload" />
   103                <Tab label="Pyroscope data" />
   104              </Tabs>
   105              <TabPanel value={tabIndexLeft} index={0}>
   106                <FileUploader
   107                  className={adhocStyles.tabPanel}
   108                  setFile={async ({ file, spyName, units }) => {
   109                    await dispatch(
   110                      uploadFile({ file, spyName, units, side: 'left' })
   111                    );
   112                    setTabIndexLeft(1);
   113                  }}
   114                />
   115              </TabPanel>
   116              <TabPanel value={tabIndexLeft} index={1}>
   117                {profilesList.type === 'loaded' && (
   118                  <FileList
   119                    className={adhocStyles.tabPanel}
   120                    profilesList={profilesList.profilesList}
   121                    selectedProfileId={selectedProfileIdLeft}
   122                    onProfileSelected={(id: string) => {
   123                      dispatch(fetchProfile({ id, side: 'left' }));
   124                    }}
   125                  />
   126                )}
   127              </TabPanel>
   128            </Box>
   129            <Box className={adhocComparisonStyles.comparisonPane}>
   130              <Tabs
   131                value={tabIndexRight}
   132                onChange={(e, value) => setTabIndexRight(value)}
   133              >
   134                <Tab label="Upload" />
   135                <Tab label="Pyroscope data" />
   136              </Tabs>
   137              <TabPanel value={tabIndexRight} index={0}>
   138                <FileUploader
   139                  className={adhocStyles.tabPanel}
   140                  setFile={async ({ file, spyName, units }) => {
   141                    await dispatch(
   142                      uploadFile({ file, spyName, units, side: 'right' })
   143                    );
   144                    setTabIndexRight(1);
   145                  }}
   146                />
   147              </TabPanel>
   148              <TabPanel value={tabIndexRight} index={1}>
   149                {profilesList.type === 'loaded' && (
   150                  <FileList
   151                    className={adhocStyles.tabPanel}
   152                    profilesList={profilesList.profilesList}
   153                    selectedProfileId={selectedProfileIdRight}
   154                    onProfileSelected={(id: string) => {
   155                      dispatch(fetchProfile({ id, side: 'right' }));
   156                    }}
   157                  />
   158                )}
   159              </TabPanel>
   160            </Box>
   161          </div>
   162          <Box>{flamegraph(diffProfile, exportToFlamegraphDotComFn)}</Box>
   163        </div>
   164      </div>
   165    );
   166  }
   167  
   168  export default AdhocDiff;