fix(ui) - tooltip click issue
This commit is contained in:
parent
317d18f3df
commit
e00cf0354e
8 changed files with 359 additions and 236 deletions
|
|
@ -21,172 +21,192 @@ import AddMetricContainer from '../DashboardWidgetGrid/AddMetricContainer';
|
|||
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
||||
|
||||
interface IProps {
|
||||
siteId: string;
|
||||
dashboardId: any;
|
||||
renderReport?: any;
|
||||
siteId: string;
|
||||
dashboardId: any;
|
||||
renderReport?: any;
|
||||
}
|
||||
|
||||
type Props = IProps & RouteComponentProps;
|
||||
|
||||
function DashboardView(props: Props) {
|
||||
const { siteId, dashboardId } = props;
|
||||
const { dashboardStore } = useStore();
|
||||
const { showModal } = useModal();
|
||||
const { siteId, dashboardId } = props;
|
||||
const { dashboardStore } = useStore();
|
||||
const { showModal } = useModal();
|
||||
|
||||
const [showTooltip, setShowTooltip] = React.useState(false);
|
||||
const [focusTitle, setFocusedInput] = React.useState(true);
|
||||
const [showEditModal, setShowEditModal] = React.useState(false);
|
||||
const [showTooltip, setShowTooltip] = React.useState(false);
|
||||
const [focusTitle, setFocusedInput] = React.useState(true);
|
||||
const [showEditModal, setShowEditModal] = React.useState(false);
|
||||
|
||||
const showAlertModal = dashboardStore.showAlertModal;
|
||||
const loading = dashboardStore.fetchingDashboard;
|
||||
const dashboard: any = dashboardStore.selectedDashboard;
|
||||
const period = dashboardStore.period;
|
||||
const showAlertModal = dashboardStore.showAlertModal;
|
||||
const loading = dashboardStore.fetchingDashboard;
|
||||
const dashboard: any = dashboardStore.selectedDashboard;
|
||||
const period = dashboardStore.period;
|
||||
|
||||
const queryParams = new URLSearchParams(props.location.search);
|
||||
const queryParams = new URLSearchParams(props.location.search);
|
||||
|
||||
const trimQuery = () => {
|
||||
if (!queryParams.has('modal')) return;
|
||||
queryParams.delete('modal');
|
||||
props.history.replace({
|
||||
search: queryParams.toString(),
|
||||
});
|
||||
};
|
||||
const pushQuery = () => {
|
||||
if (!queryParams.has('modal')) props.history.push('?modal=addMetric');
|
||||
};
|
||||
const trimQuery = () => {
|
||||
if (!queryParams.has('modal')) return;
|
||||
queryParams.delete('modal');
|
||||
props.history.replace({
|
||||
search: queryParams.toString(),
|
||||
});
|
||||
};
|
||||
const pushQuery = () => {
|
||||
if (!queryParams.has('modal')) props.history.push('?modal=addMetric');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (queryParams.has('modal')) {
|
||||
onAddWidgets();
|
||||
trimQuery();
|
||||
}
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (queryParams.has('modal')) {
|
||||
onAddWidgets();
|
||||
trimQuery();
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const isExists = dashboardStore.getDashboardById(dashboardId);
|
||||
if (!isExists) {
|
||||
props.history.push(withSiteId(`/dashboard`, siteId));
|
||||
}
|
||||
}, [dashboardId]);
|
||||
useEffect(() => {
|
||||
const isExists = dashboardStore.getDashboardById(dashboardId);
|
||||
if (!isExists) {
|
||||
props.history.push(withSiteId(`/dashboard`, siteId));
|
||||
}
|
||||
}, [dashboardId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!dashboard || !dashboard.dashboardId) return;
|
||||
dashboardStore.fetch(dashboard.dashboardId);
|
||||
}, [dashboard]);
|
||||
useEffect(() => {
|
||||
if (!dashboard || !dashboard.dashboardId) return;
|
||||
dashboardStore.fetch(dashboard.dashboardId);
|
||||
}, [dashboard]);
|
||||
|
||||
const onAddWidgets = () => {
|
||||
dashboardStore.initDashboard(dashboard);
|
||||
showModal(<DashboardModal siteId={siteId} onMetricAdd={pushQuery} dashboardId={dashboardId} />, { right: true });
|
||||
};
|
||||
|
||||
const onEdit = (isTitle: boolean) => {
|
||||
dashboardStore.initDashboard(dashboard);
|
||||
setFocusedInput(isTitle);
|
||||
setShowEditModal(true);
|
||||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
if (
|
||||
await confirm({
|
||||
header: 'Confirm',
|
||||
confirmButton: 'Yes, delete',
|
||||
confirmation: `Are you sure you want to permanently delete this Dashboard?`,
|
||||
})
|
||||
) {
|
||||
dashboardStore.deleteDashboard(dashboard).then(() => {
|
||||
props.history.push(withSiteId(`/dashboard`, siteId));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (!dashboard) return null;
|
||||
|
||||
return (
|
||||
<Loader loading={loading}>
|
||||
<div style={{ maxWidth: '1300px', margin: 'auto' }}>
|
||||
<DashboardEditModal show={showEditModal} closeHandler={() => setShowEditModal(false)} focusTitle={focusTitle} />
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{
|
||||
label: 'Dashboards',
|
||||
to: withSiteId('/dashboard', siteId),
|
||||
},
|
||||
{ label: (dashboard && dashboard.name) || '' },
|
||||
]}
|
||||
/>
|
||||
<div className="flex items-center mb-2 justify-between">
|
||||
<div className="flex items-center" style={{ flex: 3 }}>
|
||||
<PageTitle
|
||||
title={
|
||||
// @ts-ignore
|
||||
<Tooltip delay={100} arrow title="Double click to rename">
|
||||
{dashboard?.name}
|
||||
</Tooltip>
|
||||
}
|
||||
onDoubleClick={() => onEdit(true)}
|
||||
className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer"
|
||||
actionButton={
|
||||
/* @ts-ignore */
|
||||
<Tooltip
|
||||
open={showTooltip}
|
||||
interactive
|
||||
useContext
|
||||
// @ts-ignore
|
||||
theme="nopadding"
|
||||
hideDelay={0}
|
||||
duration={0}
|
||||
distance={20}
|
||||
html={
|
||||
<div style={{ padding: 0 }}>
|
||||
<OutsideClickDetectingDiv onClickOutside={() => setShowTooltip(false)}>
|
||||
<AddMetricContainer onAction={() => setShowTooltip(false)} isPopup siteId={siteId} />
|
||||
</OutsideClickDetectingDiv>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Button variant="primary" onClick={() => setShowTooltip(true)}>
|
||||
Add Metric
|
||||
</Button>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center" style={{ flex: 1, justifyContent: 'end' }}>
|
||||
<div className="flex items-center flex-shrink-0 justify-end" style={{ width: '300px' }}>
|
||||
<SelectDateRange
|
||||
style={{ width: '300px' }}
|
||||
period={period}
|
||||
onChange={(period: any) => dashboardStore.setPeriod(period)}
|
||||
right={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="mx-4" />
|
||||
<div className="flex items-center flex-shrink-0">
|
||||
<DashboardOptions
|
||||
editHandler={onEdit}
|
||||
deleteHandler={onDelete}
|
||||
renderReport={props.renderReport}
|
||||
isTitlePresent={!!dashboard?.description}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pb-4">
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip delay={100} arrow title="Double click to rename" className='w-fit !block'>
|
||||
<h2
|
||||
className="my-2 font-normal w-fit text-disabled-text border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer"
|
||||
onDoubleClick={() => onEdit(false)}
|
||||
>
|
||||
{dashboard?.description || 'Describe the purpose of this dashboard'}
|
||||
</h2>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<DashboardWidgetGrid siteId={siteId} dashboardId={dashboardId} onEditHandler={onAddWidgets} id="report" />
|
||||
<AlertFormModal showModal={showAlertModal} onClose={() => dashboardStore.updateKey('showAlertModal', false)} />
|
||||
</div>
|
||||
</Loader>
|
||||
const onAddWidgets = () => {
|
||||
dashboardStore.initDashboard(dashboard);
|
||||
showModal(
|
||||
<DashboardModal siteId={siteId} onMetricAdd={pushQuery} dashboardId={dashboardId} />,
|
||||
{ right: true }
|
||||
);
|
||||
};
|
||||
|
||||
const onEdit = (isTitle: boolean) => {
|
||||
dashboardStore.initDashboard(dashboard);
|
||||
setFocusedInput(isTitle);
|
||||
setShowEditModal(true);
|
||||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
if (
|
||||
await confirm({
|
||||
header: 'Confirm',
|
||||
confirmButton: 'Yes, delete',
|
||||
confirmation: `Are you sure you want to permanently delete this Dashboard?`,
|
||||
})
|
||||
) {
|
||||
dashboardStore.deleteDashboard(dashboard).then(() => {
|
||||
props.history.push(withSiteId(`/dashboard`, siteId));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (!dashboard) return null;
|
||||
|
||||
return (
|
||||
<Loader loading={loading}>
|
||||
<div style={{ maxWidth: '1300px', margin: 'auto' }}>
|
||||
<DashboardEditModal
|
||||
show={showEditModal}
|
||||
closeHandler={() => setShowEditModal(false)}
|
||||
focusTitle={focusTitle}
|
||||
/>
|
||||
<Breadcrumb
|
||||
items={[
|
||||
{
|
||||
label: 'Dashboards',
|
||||
to: withSiteId('/dashboard', siteId),
|
||||
},
|
||||
{ label: (dashboard && dashboard.name) || '' },
|
||||
]}
|
||||
/>
|
||||
<div className="flex items-center mb-2 justify-between">
|
||||
<div className="flex items-center" style={{ flex: 3 }}>
|
||||
<PageTitle
|
||||
title={
|
||||
// @ts-ignore
|
||||
<Tooltip delay={100} arrow title="Double click to rename">
|
||||
{dashboard?.name}
|
||||
</Tooltip>
|
||||
}
|
||||
onDoubleClick={() => onEdit(true)}
|
||||
className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer"
|
||||
actionButton={
|
||||
<OutsideClickDetectingDiv onClickOutside={() => setShowTooltip(false)}>
|
||||
<Tooltip
|
||||
open={showTooltip}
|
||||
interactive
|
||||
useContext
|
||||
// @ts-ignore
|
||||
theme="nopadding"
|
||||
hideDelay={0}
|
||||
duration={0}
|
||||
distance={20}
|
||||
html={
|
||||
<div style={{ padding: 0 }}>
|
||||
<AddMetricContainer
|
||||
onAction={() => setShowTooltip(false)}
|
||||
isPopup
|
||||
siteId={siteId}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Button variant="primary" onClick={() => setShowTooltip(true)}>
|
||||
Add Metric
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</OutsideClickDetectingDiv>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center" style={{ flex: 1, justifyContent: 'end' }}>
|
||||
<div className="flex items-center flex-shrink-0 justify-end" style={{ width: '300px' }}>
|
||||
<SelectDateRange
|
||||
style={{ width: '300px' }}
|
||||
period={period}
|
||||
onChange={(period: any) => dashboardStore.setPeriod(period)}
|
||||
right={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="mx-4" />
|
||||
<div className="flex items-center flex-shrink-0">
|
||||
<DashboardOptions
|
||||
editHandler={onEdit}
|
||||
deleteHandler={onDelete}
|
||||
renderReport={props.renderReport}
|
||||
isTitlePresent={!!dashboard?.description}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pb-4">
|
||||
{/* @ts-ignore */}
|
||||
<Tooltip delay={100} arrow title="Double click to rename" className="w-fit !block">
|
||||
<h2
|
||||
className="my-2 font-normal w-fit text-disabled-text border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer"
|
||||
onDoubleClick={() => onEdit(false)}
|
||||
>
|
||||
{dashboard?.description || 'Describe the purpose of this dashboard'}
|
||||
</h2>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<DashboardWidgetGrid
|
||||
siteId={siteId}
|
||||
dashboardId={dashboardId}
|
||||
onEditHandler={onAddWidgets}
|
||||
id="report"
|
||||
/>
|
||||
<AlertFormModal
|
||||
showModal={showAlertModal}
|
||||
onClose={() => dashboardStore.updateKey('showAlertModal', false)}
|
||||
/>
|
||||
</div>
|
||||
</Loader>
|
||||
);
|
||||
}
|
||||
// @ts-ignore
|
||||
export default withPageTitle('Dashboards - OpenReplay')(withReport(withRouter(withModal(observer(DashboardView)))));
|
||||
export default withPageTitle('Dashboards - OpenReplay')(
|
||||
withReport(withRouter(withModal(observer(DashboardView))))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,24 +5,27 @@ import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
|||
import IssuesModal from './IssuesModal';
|
||||
import { fetchProjects, fetchMeta } from 'Duck/assignments';
|
||||
import stl from './issues.module.css';
|
||||
import { Tooltip } from 'react-tippy'
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
@connect(state => ({
|
||||
issues: state.getIn(['assignments', 'list']),
|
||||
metaLoading: state.getIn(['assignments', 'fetchMeta', 'loading']),
|
||||
projects: state.getIn(['assignments', 'projects']),
|
||||
projectsFetched: state.getIn(['assignments', 'projectsFetched']),
|
||||
activeIssue: state.getIn(['assignments', 'activeIssue']),
|
||||
fetchIssueLoading: state.getIn(['assignments', 'fetchAssignment', 'loading']),
|
||||
fetchIssuesLoading: state.getIn(['assignments', 'fetchAssignments', 'loading']),
|
||||
projectsLoading: state.getIn(['assignments', 'fetchProjects', 'loading']),
|
||||
issuesIntegration: state.getIn([ 'issues', 'list']).first() || {},
|
||||
@connect(
|
||||
(state) => ({
|
||||
issues: state.getIn(['assignments', 'list']),
|
||||
metaLoading: state.getIn(['assignments', 'fetchMeta', 'loading']),
|
||||
projects: state.getIn(['assignments', 'projects']),
|
||||
projectsFetched: state.getIn(['assignments', 'projectsFetched']),
|
||||
activeIssue: state.getIn(['assignments', 'activeIssue']),
|
||||
fetchIssueLoading: state.getIn(['assignments', 'fetchAssignment', 'loading']),
|
||||
fetchIssuesLoading: state.getIn(['assignments', 'fetchAssignments', 'loading']),
|
||||
projectsLoading: state.getIn(['assignments', 'fetchProjects', 'loading']),
|
||||
issuesIntegration: state.getIn(['issues', 'list']).first() || {},
|
||||
|
||||
jiraConfig: state.getIn([ 'issues', 'list' ]).first(),
|
||||
issuesFetched: state.getIn([ 'issues', 'issuesFetched' ]),
|
||||
}), { fetchMeta, fetchProjects })
|
||||
jiraConfig: state.getIn(['issues', 'list']).first(),
|
||||
issuesFetched: state.getIn(['issues', 'issuesFetched']),
|
||||
}),
|
||||
{ fetchMeta, fetchProjects }
|
||||
)
|
||||
class Issues extends React.Component {
|
||||
state = {showModal: false };
|
||||
state = { showModal: false };
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -31,64 +34,79 @@ class Issues extends React.Component {
|
|||
|
||||
closeModal = () => {
|
||||
this.setState({ showModal: false });
|
||||
}
|
||||
};
|
||||
|
||||
showIssuesList = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState({ showModal: true });
|
||||
}
|
||||
};
|
||||
|
||||
handleOpen = () => {
|
||||
this.setState({ showModal: true });
|
||||
if (!this.props.projectsFetched) { // cache projects fetch
|
||||
this.props.fetchProjects().then(function() {
|
||||
const { projects } = this.props;
|
||||
if (projects && projects.first()) {
|
||||
this.props.fetchMeta(projects.first().id)
|
||||
}
|
||||
}.bind(this))
|
||||
if (!this.props.projectsFetched) {
|
||||
// cache projects fetch
|
||||
this.props.fetchProjects().then(
|
||||
function () {
|
||||
const { projects } = this.props;
|
||||
if (projects && projects.first()) {
|
||||
this.props.fetchMeta(projects.first().id);
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
sessionId, isModalDisplayed, projectsLoading, metaLoading, fetchIssuesLoading, issuesIntegration
|
||||
sessionId,
|
||||
isModalDisplayed,
|
||||
projectsLoading,
|
||||
metaLoading,
|
||||
fetchIssuesLoading,
|
||||
issuesIntegration,
|
||||
} = this.props;
|
||||
const provider = issuesIntegration.provider
|
||||
const provider = issuesIntegration.provider;
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className={ stl.buttonWrapper} onClick={this.handleOpen}>
|
||||
<div className="relative">
|
||||
<div className={stl.buttonWrapper}>
|
||||
<OutsideClickDetectingDiv onClickOutside={this.closeModal}>
|
||||
<Tooltip
|
||||
open={this.state.showModal}
|
||||
position="bottom"
|
||||
interactive
|
||||
// animation="shift"
|
||||
trigger="click"
|
||||
unmountHTMLWhenHide
|
||||
// @ts-ignore
|
||||
theme='light'
|
||||
useContext
|
||||
theme="light"
|
||||
arrow
|
||||
html={
|
||||
<OutsideClickDetectingDiv onClickOutside={this.closeModal}>
|
||||
<div>
|
||||
<IssuesModal
|
||||
provider={provider}
|
||||
sessionId={ sessionId }
|
||||
closeHandler={ this.closeModal }
|
||||
sessionId={sessionId}
|
||||
closeHandler={this.closeModal}
|
||||
/>
|
||||
</OutsideClickDetectingDiv>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="flex items-center" onClick={this.handleOpen} disabled={!isModalDisplayed && (metaLoading || fetchIssuesLoading || projectsLoading)}>
|
||||
<Icon name={ `integrations/${ provider === 'jira' ? 'jira' : 'github'}` } size="16" />
|
||||
<span className="ml-2">Create Issue</span>
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center"
|
||||
onClick={this.handleOpen}
|
||||
disabled={
|
||||
!isModalDisplayed && (metaLoading || fetchIssuesLoading || projectsLoading)
|
||||
}
|
||||
>
|
||||
<Icon name={`integrations/${provider === 'jira' ? 'jira' : 'github'}`} size="16" />
|
||||
<span className="ml-2">Create Issue</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</OutsideClickDetectingDiv>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default Issues;
|
||||
|
|
|
|||
|
|
@ -78,8 +78,6 @@ function SubHeader(props) {
|
|||
);
|
||||
}
|
||||
|
||||
const SubH = connectPlayer(
|
||||
(state) => ({ currentLocation: state.location })
|
||||
)(SubHeader);
|
||||
const SubH = connectPlayer((state) => ({ currentLocation: state.location }))(SubHeader);
|
||||
|
||||
export default React.memo(SubH);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { IconButton } from 'UI';
|
||||
import { Button, Icon } from 'UI';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { connectPlayer } from 'Player';
|
||||
|
||||
|
|
@ -7,12 +7,13 @@ interface Props {
|
|||
content: string;
|
||||
time: any;
|
||||
}
|
||||
|
||||
function SessionCopyLink({ content = '', time }: Props) {
|
||||
const [copied, setCopied] = React.useState(false)
|
||||
const [copied, setCopied] = React.useState(false);
|
||||
|
||||
const copyHandler = () => {
|
||||
setCopied(true);
|
||||
copy(window.location.origin + window.location.pathname + '?jumpto=' + Math.round(time));
|
||||
copy(window.location.origin + window.location.pathname + '?jumpto=' + Math.round(time));
|
||||
setTimeout(() => {
|
||||
setCopied(false);
|
||||
}, 1000);
|
||||
|
|
@ -20,10 +21,25 @@ function SessionCopyLink({ content = '', time }: Props) {
|
|||
|
||||
return (
|
||||
<div className="flex justify-between items-center w-full mt-2">
|
||||
<IconButton label="Copy URL at current time" primaryText icon="link-45deg" onClick={copyHandler} />
|
||||
{ copied && <div className="color-gray-medium">Copied</div> }
|
||||
{/* <IconButton
|
||||
label="Copy URL at current time"
|
||||
primaryText
|
||||
icon="link-45deg"
|
||||
onClick={copyHandler}
|
||||
/> */}
|
||||
<Button variant="text-primary" onClick={copyHandler}>
|
||||
<>
|
||||
<Icon name="link-45deg" className="mr-2" color="teal" size="18" />
|
||||
<span>Copy URL at current time</span>
|
||||
</>
|
||||
</Button>
|
||||
{copied && <div className="color-gray-medium">Copied</div>}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionCopyLink
|
||||
const SessionCopyLinkCompo = connectPlayer((state: any) => ({
|
||||
time: state.time,
|
||||
}))(SessionCopyLink);
|
||||
|
||||
export default React.memo(SessionCopyLinkCompo);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ import cn from 'classnames';
|
|||
import { fetchList, init } from 'Duck/integrations/slack';
|
||||
import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv';
|
||||
|
||||
@connectPlayer((state) => ({
|
||||
time: state.time,
|
||||
}))
|
||||
// @connectPlayer((state) => ({
|
||||
// time: state.time,
|
||||
// }))
|
||||
@connect(
|
||||
(state) => ({
|
||||
channels: state.getIn(['slack', 'list']),
|
||||
|
|
@ -58,7 +58,7 @@ export default class SharePopup extends React.PureComponent {
|
|||
};
|
||||
|
||||
handleSuccess = () => {
|
||||
this.setState({ isOpen: false, comment: '' })
|
||||
this.setState({ isOpen: false, comment: '' });
|
||||
toast.success('Sent to Slack.');
|
||||
};
|
||||
|
||||
|
|
@ -69,31 +69,31 @@ export default class SharePopup extends React.PureComponent {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { trigger, loading, channels, showCopyLink = false, time } = this.props;
|
||||
const { trigger, loading, channels, showCopyLink = false } = this.props;
|
||||
const { comment, channelId, isOpen } = this.state;
|
||||
|
||||
const options = channels
|
||||
.map(({ webhookId, name }) => ({ value: webhookId, label: name }))
|
||||
.toJS();
|
||||
return (
|
||||
<Tooltip
|
||||
open={isOpen}
|
||||
theme="light"
|
||||
interactive
|
||||
position="bottom"
|
||||
unmountHTMLWhenHide
|
||||
useContext
|
||||
arrow
|
||||
trigger="click"
|
||||
shown={this.handleOpen}
|
||||
// beforeHidden={this.handleClose}
|
||||
html={
|
||||
<OutsideClickDetectingDiv
|
||||
className={cn('relative flex items-center')}
|
||||
onClickOutside={() => {
|
||||
this.setState({ isOpen: false })
|
||||
}}
|
||||
>
|
||||
<OutsideClickDetectingDiv
|
||||
className={cn('relative flex items-center')}
|
||||
onClickOutside={() => {
|
||||
this.setState({ isOpen: false });
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
open={isOpen}
|
||||
theme="light"
|
||||
interactive
|
||||
position="bottom"
|
||||
unmountHTMLWhenHide
|
||||
useContext
|
||||
arrow
|
||||
trigger="click"
|
||||
shown={this.handleOpen}
|
||||
// beforeHidden={this.handleClose}
|
||||
html={
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.header}>
|
||||
<div className={cn(styles.title, 'text-lg')}>Share this session link to Slack</div>
|
||||
|
|
@ -105,7 +105,7 @@ export default class SharePopup extends React.PureComponent {
|
|||
</div>
|
||||
{showCopyLink && (
|
||||
<div className={styles.footer}>
|
||||
<SessionCopyLink time={time} />
|
||||
<SessionCopyLink />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
|
@ -132,7 +132,7 @@ export default class SharePopup extends React.PureComponent {
|
|||
className="mr-4"
|
||||
/>
|
||||
<div>
|
||||
<Button onClick={this.share} primary>
|
||||
<Button onClick={this.share} variant="primary">
|
||||
<div className="flex items-center">
|
||||
<Icon name="integrations/slack-bw" size="18" marginRight="10" />
|
||||
{loading ? 'Sending...' : 'Send'}
|
||||
|
|
@ -142,16 +142,16 @@ export default class SharePopup extends React.PureComponent {
|
|||
</div>
|
||||
</div>
|
||||
<div className={styles.footer}>
|
||||
<SessionCopyLink time={time} />
|
||||
<SessionCopyLink />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</OutsideClickDetectingDiv>
|
||||
}
|
||||
>
|
||||
<span onClick={this.onClickHandler}>{trigger}</span>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<div onClick={this.onClickHandler}>{trigger}</div>
|
||||
</Tooltip>
|
||||
</OutsideClickDetectingDiv>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
import React, { cloneElement, useMemo, useState } from 'react';
|
||||
import {
|
||||
Placement,
|
||||
offset,
|
||||
flip,
|
||||
shift,
|
||||
autoUpdate,
|
||||
useFloating,
|
||||
useInteractions,
|
||||
useHover,
|
||||
useFocus,
|
||||
useRole,
|
||||
useDismiss,
|
||||
useClick,
|
||||
} from '@floating-ui/react-dom-interactions';
|
||||
import { mergeRefs } from 'react-merge-refs';
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
placement?: Placement;
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
function AnimatedTooltip({ children, label, placement = 'top' }: Props) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { x, y, reference, floating, strategy, context } = useFloating({
|
||||
placement,
|
||||
open,
|
||||
onOpenChange: setOpen,
|
||||
middleware: [offset(5), flip(), shift({ padding: 8 })],
|
||||
whileElementsMounted: autoUpdate,
|
||||
});
|
||||
|
||||
const { getReferenceProps, getFloatingProps } = useInteractions([
|
||||
// useHover(context),
|
||||
useFocus(context),
|
||||
useRole(context, { role: 'tooltip' }),
|
||||
useDismiss(context),
|
||||
useClick(context),
|
||||
]);
|
||||
|
||||
// Preserve the consumer's ref
|
||||
const ref = useMemo(() => mergeRefs([reference, (children as any).ref]), [reference, children]);
|
||||
const ppp = getReferenceProps({ ref, ...children.props });
|
||||
// console.log('ppp', ppp);
|
||||
return (
|
||||
<div>
|
||||
{/* {cloneElement(children, getReferenceProps({ ref, ...children.props }))} */}
|
||||
<button ref={reference} {...getReferenceProps({ ref, ...children.props })}>Button</button>
|
||||
{open && (
|
||||
<div
|
||||
ref={floating}
|
||||
className="Tooltip"
|
||||
style={{
|
||||
position: strategy,
|
||||
top: y ?? 0,
|
||||
left: x ?? 0,
|
||||
}}
|
||||
{...getFloatingProps()}
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AnimatedTooltip;
|
||||
1
frontend/app/components/ui/AnimatedTooltip/index.ts
Normal file
1
frontend/app/components/ui/AnimatedTooltip/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './AnimatedTooltip';
|
||||
|
|
@ -57,3 +57,4 @@ export { default as Input } from './Input';
|
|||
export { default as Form } from './Form';
|
||||
export { default as Modal } from './Modal';
|
||||
export { default as Message } from './Message';
|
||||
export { default as AnimatedTooltip } from './AnimatedTooltip';
|
||||
Loading…
Add table
Reference in a new issue