// Copyright 2022 The Parca Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import {Icon} from '@iconify/react'; import cx from 'classnames'; import {useQueryState} from 'nuqs'; import {Item, Menu, Submenu} from 'react-contexify'; import 'react-contexify/dist/ReactContexify.css'; import {useParcaContext} from '@parca/components'; import {valueFormatter} from '@parca/utilities'; import {type Row} from '.'; import {getTextForCumulative} from '../ProfileFlameGraph/FlameGraphArrow/utils'; import {stringParam} from '../hooks/urlParsers'; import {useDashboardItems} from '../hooks/useDashboardItems'; import {truncateString} from '../utils'; import {type ColumnName} from './utils/functions'; interface TableContextMenuProps { menuId: string; row: Row | null; unit?: string; total?: bigint; totalUnfiltered?: bigint; columnVisibility?: Record; } const TableContextMenu = ({ menuId, row, unit, total, totalUnfiltered, columnVisibility, }: TableContextMenuProps): React.JSX.Element => { const [_, setSandwichFunctionName] = useQueryState('sandwich_function_name', stringParam); const {dashboardItems, setDashboardItems} = useDashboardItems(); const {enableSandwichView, isDarkMode} = useParcaContext(); const onSandwichViewSelect = (): void => { if (row?.name != null && row.name.length > 0) { void setSandwichFunctionName(row.name.trim()); if (!dashboardItems.includes('sandwich')) { setDashboardItems([...dashboardItems, 'sandwich']); } } }; const handleCopyItem = (text: string): void => { void navigator.clipboard.writeText(text); }; const isColumnVisible = (columnName: ColumnName): boolean => { return columnVisibility?.[columnName] ?? true; }; const valuesToCopy = row !== null ? [ ...(isColumnVisible('flat') ? [ { id: 'Flat', value: total !== null && total !== undefined && totalUnfiltered !== null && totalUnfiltered !== undefined ? getTextForCumulative(row.flat, total, totalUnfiltered, unit ?? '') : valueFormatter(row.flat, unit ?? '', 1), }, ] : []), ...(isColumnVisible('flatPercentage') ? [ { id: 'Flat (%)', value: total !== null && total !== undefined && totalUnfiltered !== null && totalUnfiltered !== undefined ? getTextForCumulative(row.flat, total, totalUnfiltered, unit ?? '') : valueFormatter(row.flat, unit ?? '', 1), }, ] : []), ...(isColumnVisible('flatDiff') ? [ { id: 'Flat Diff', value: row.flatDiff !== 0n ? valueFormatter(row.flatDiff, unit ?? '', 1) : '', }, ] : []), ...(isColumnVisible('flatDiffPercentage') ? [ { id: 'Flat Diff (%)', value: row.flatDiff !== 0n ? valueFormatter(row.flatDiff, unit ?? '', 1) : '', }, ] : []), ...(isColumnVisible('cumulative') ? [ { id: 'Cumulative', value: total !== null && total !== undefined && totalUnfiltered !== null && totalUnfiltered !== undefined ? getTextForCumulative(row.cumulative, total, totalUnfiltered, unit ?? '') : valueFormatter(row.cumulative, unit ?? '', 1), }, ] : []), ...(isColumnVisible('cumulativePercentage') ? [ { id: 'Cumulative (%)', value: total !== null && total !== undefined && totalUnfiltered !== null && totalUnfiltered !== undefined ? getTextForCumulative(row.cumulative, total, totalUnfiltered, unit ?? '') : valueFormatter(row.cumulative, unit ?? '', 1), }, ] : []), ...(isColumnVisible('cumulativeDiff') ? [ { id: 'Cumulative Diff', value: row.cumulativeDiff !== 0n ? valueFormatter(row.cumulativeDiff, unit ?? '', 1) : '', }, ] : []), ...(isColumnVisible('cumulativeDiffPercentage') ? [ { id: 'Cumulative Diff (%)', value: row.cumulativeDiff !== 0n ? valueFormatter(row.cumulativeDiff, unit ?? '', 1) : '', }, ] : []), ...(isColumnVisible('name') ? [ { id: 'Name', value: row.name ?? '', }, ] : []), ...(isColumnVisible('functionSystemName') ? [{id: 'Function System Name', value: row.functionSystemName ?? ''}] : []), ...(isColumnVisible('functionFileName') ? [{id: 'Function File Name', value: row.functionFileName ?? ''}] : []), ...(isColumnVisible('mappingFile') ? [{id: 'Mapping File', value: row.mappingFile ?? ''}] : []), ].flat() : []; const nonEmptyValuesToCopy = valuesToCopy.filter(({value}) => value !== ''); const isMenuDisabled = row === null || enableSandwichView !== true; return (
{dashboardItems.includes('sandwich') ? 'Focus sandwich on this frame.' : 'Show in sandwich'}  alpha
Copy
} disabled={row === null} >
{nonEmptyValuesToCopy.map(({id, value}: {id: string; value: string}) => ( handleCopyItem(value)} className="dark:bg-gray-800" >
{id}
{truncateString(value, 30)}
))}
); }; export default TableContextMenu;