// 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, {useState} from 'react'; import {Icon} from '@iconify/react'; import {QueryRequest, QueryServiceClient} from '@parca/client'; import {Button, Dropdown, Modal, useGrpcMetadata, useParcaContext} from '@parca/components'; import {ProfileSource} from '../../../ProfileSource'; import ResultBox from './ResultBox'; interface Props { profileSource?: ProfileSource; queryClient?: QueryServiceClient; queryRequest?: QueryRequest; onDownloadPProf: () => void; pprofdownloading: boolean; profileViewExternalSubActions: React.ReactNode; } interface ProfileShareModalProps { queryRequest: QueryRequest; queryClient: QueryServiceClient; isOpen: boolean; closeModal: () => void; } const ProfileShareModal = ({ isOpen, closeModal, queryRequest, queryClient, }: ProfileShareModalProps): JSX.Element => { const [isShared, setIsShared] = useState(false); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); const [description, setDescription] = useState(''); const [sharedLink, setSharedLink] = useState(''); const {Spinner} = useParcaContext(); const metadata = useGrpcMetadata(); const isFormDataValid = (): boolean => true; const handleSubmit: () => Promise = async () => { try { setLoading(true); const {response} = await queryClient.shareProfile( {queryRequest, description}, {meta: metadata} ); setSharedLink(response.link); setLoading(false); setIsShared(true); } catch (err) { if (err instanceof Error) { console.error(err); setLoading(false); // https://github.com/microsoft/TypeScript/issues/38347 // eslint-disable-next-line @typescript-eslint/no-base-to-string setError(err.toString()); } } }; const onClose = (): void => { setLoading(false); setError(''); setDescription(''); setIsShared(false); closeModal(); }; return (

Note: Shared profiles can be accessed by anyone with the link, even from people outside your organisation.

{!isShared || error?.length > 0 ? ( <>

Enter a description (optional)

{error !== '' ?

Something went wrong please try again

: null} ) : ( <>
)}
); }; const ShareButton = ({ queryRequest, queryClient, profileSource, onDownloadPProf, pprofdownloading, profileViewExternalSubActions, }: Props): JSX.Element => { const [showProfileShareModal, setShowProfileShareModal] = useState(false); const actions = [ { key: 'shareProfile', label: 'Share profile via link', onSelect: () => setShowProfileShareModal(true), id: 'h-share-profile-button', disabled: profileSource === undefined && queryClient === undefined && queryRequest === undefined, icon: 'material-symbols-light:link', }, { key: 'downloadProfile', label: pprofdownloading != null && pprofdownloading ? 'Downloading...' : 'Download as pprof', onSelect: () => onDownloadPProf(), id: 'h-download-pprof', disabled: pprofdownloading, icon: 'material-symbols:download', }, ]; return ( <> {profileViewExternalSubActions != null ? ( <> ) : ( <>
Share
} > actions {actions.map(item => (
{item.label}
))}
{profileSource !== undefined && queryClient !== undefined && queryRequest !== undefined && ( setShowProfileShareModal(false)} queryRequest={queryRequest} queryClient={queryClient} /> )} )} ); }; export default ShareButton;