// 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 React from 'react'; import {Icon} from '@iconify/react'; import cx from 'classnames'; import {USER_PREFERENCES, useCurrentColorProfile, useUserPreference} from '@parca/hooks'; import {EVERYTHING_ELSE, selectDarkMode, useAppSelector} from '@parca/store'; import {getMappingColors} from '../../ProfileFlameGraph/FlameGraphArrow'; import useMappingList from '../../ProfileFlameGraph/FlameGraphArrow/useMappingList'; import {useColorBy} from '../../hooks/useColorBy'; import {useProfileFilters} from './ProfileFilters/useProfileFilters'; interface Props { mappings?: string[]; loading?: boolean; compareMode?: boolean; } const ColorStackLegend = ({mappings, compareMode = false, loading}: Props): React.JSX.Element => { const isDarkMode = useAppSelector(selectDarkMode); const currentColorProfile = useCurrentColorProfile(); const [colorProfileName] = useUserPreference( USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key ); const {colorBy} = useColorBy(); const {appliedFilters, removeExcludeBinary, excludeBinary} = useProfileFilters(); const currentBinaryFilters = (appliedFilters ?? []) .filter(f => f.type === 'frame' && f.field === 'binary') .map(f => f.value); const mappingsList = useMappingList(mappings); const mappingColors = getMappingColors(mappingsList, isDarkMode, currentColorProfile); const stackColorArray = Object.entries(mappingColors).sort(([featureA], [featureB]) => { if (featureA === EVERYTHING_ELSE) { return 1; } if (featureB === EVERYTHING_ELSE) { return -1; } return featureA?.localeCompare(featureB ?? '') ?? 0; }); if (stackColorArray.length === 0 && loading === false) { return <>; } if (Object.entries(mappingColors).length === 0) { return <>; } if (colorProfileName === 'default' || compareMode) { return <>; } return (
{stackColorArray.map(([feature, color]) => { const filteringAllowed = feature !== EVERYTHING_ELSE; const isHighlighted = currentBinaryFilters.includes(feature); return (
{ if (!filteringAllowed || isHighlighted || colorBy !== 'binary') { return; } // Remove the exclude filter for this binary removeExcludeBinary(feature); }} >
{feature}
{isHighlighted && ( { // Find and remove the filter for this binary excludeBinary(feature); e.stopPropagation(); }} /> )}
); })}
); }; export default ColorStackLegend;