fix random issues (tooltip, assist, button) (#596)
* fix(ui) - live player loader * change(ui) - removed unused * change(ui) - button changes * fix(ui) - tooltip changes
This commit is contained in:
parent
d1806b08ef
commit
de9a11a7da
10 changed files with 287 additions and 298 deletions
|
|
@ -1,153 +1,166 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import { Popup, Icon, IconButton } from 'UI'
|
||||
import { connect } from 'react-redux'
|
||||
import cn from 'classnames'
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Popup, Icon, Button, IconButton } from 'UI';
|
||||
import { connect } from 'react-redux';
|
||||
import cn from 'classnames';
|
||||
import { toggleChatWindow } from 'Duck/sessions';
|
||||
import { connectPlayer } from 'Player/store';
|
||||
import ChatWindow from '../../ChatWindow';
|
||||
import { callPeer, requestReleaseRemoteControl, toggleAnnotation } from 'Player'
|
||||
import { callPeer, requestReleaseRemoteControl, toggleAnnotation } from 'Player';
|
||||
import { CallingState, ConnectionStatus, RemoteControlStatus } from 'Player/MessageDistributor/managers/AssistManager';
|
||||
import RequestLocalStream from 'Player/MessageDistributor/managers/LocalStream';
|
||||
import type { LocalStream } from 'Player/MessageDistributor/managers/LocalStream';
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
import { confirm } from 'UI';
|
||||
import stl from './AassistActions.module.css'
|
||||
import stl from './AassistActions.module.css';
|
||||
|
||||
function onClose(stream) {
|
||||
stream.getTracks().forEach(t=>t.stop());
|
||||
stream.getTracks().forEach((t) => t.stop());
|
||||
}
|
||||
|
||||
function onReject() {
|
||||
toast.info(`Call was rejected.`);
|
||||
toast.info(`Call was rejected.`);
|
||||
}
|
||||
|
||||
function onError(e) {
|
||||
toast.error(typeof e === 'string' ? e : e.message);
|
||||
toast.error(typeof e === 'string' ? e : e.message);
|
||||
}
|
||||
|
||||
|
||||
interface Props {
|
||||
userId: String,
|
||||
toggleChatWindow: (state) => void,
|
||||
calling: CallingState,
|
||||
annotating: boolean,
|
||||
peerConnectionStatus: ConnectionStatus,
|
||||
remoteControlStatus: RemoteControlStatus,
|
||||
hasPermission: boolean,
|
||||
isEnterprise: boolean,
|
||||
userId: String;
|
||||
toggleChatWindow: (state) => void;
|
||||
calling: CallingState;
|
||||
annotating: boolean;
|
||||
peerConnectionStatus: ConnectionStatus;
|
||||
remoteControlStatus: RemoteControlStatus;
|
||||
hasPermission: boolean;
|
||||
isEnterprise: boolean;
|
||||
}
|
||||
|
||||
function AssistActions({ toggleChatWindow, userId, calling, annotating, peerConnectionStatus, remoteControlStatus, hasPermission, isEnterprise }: Props) {
|
||||
const [ incomeStream, setIncomeStream ] = useState<MediaStream | null>(null);
|
||||
const [ localStream, setLocalStream ] = useState<LocalStream | null>(null);
|
||||
const [ callObject, setCallObject ] = useState<{ end: ()=>void } | null >(null);
|
||||
function AssistActions({
|
||||
toggleChatWindow,
|
||||
userId,
|
||||
calling,
|
||||
annotating,
|
||||
peerConnectionStatus,
|
||||
remoteControlStatus,
|
||||
hasPermission,
|
||||
isEnterprise,
|
||||
}: Props) {
|
||||
const [incomeStream, setIncomeStream] = useState<MediaStream | null>(null);
|
||||
const [localStream, setLocalStream] = useState<LocalStream | null>(null);
|
||||
const [callObject, setCallObject] = useState<{ end: () => void } | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
return callObject?.end()
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
return callObject?.end();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (peerConnectionStatus == ConnectionStatus.Disconnected) {
|
||||
toast.info(`Live session was closed.`);
|
||||
}
|
||||
}, [peerConnectionStatus])
|
||||
|
||||
function call() {
|
||||
RequestLocalStream().then(lStream => {
|
||||
setLocalStream(lStream);
|
||||
setCallObject(callPeer(
|
||||
lStream,
|
||||
setIncomeStream,
|
||||
lStream.stop.bind(lStream),
|
||||
onReject,
|
||||
onError
|
||||
));
|
||||
}).catch(onError)
|
||||
}
|
||||
|
||||
const confirmCall = async () => {
|
||||
if (await confirm({
|
||||
header: 'Start Call',
|
||||
confirmButton: 'Call',
|
||||
confirmation: `Are you sure you want to call ${userId ? userId : 'User'}?`
|
||||
})) {
|
||||
call()
|
||||
}
|
||||
}
|
||||
|
||||
const onCall = calling === CallingState.OnCall || calling === CallingState.Reconnecting
|
||||
const cannotCall = (peerConnectionStatus !== ConnectionStatus.Connected) || (isEnterprise && !hasPermission)
|
||||
const remoteActive = remoteControlStatus === RemoteControlStatus.Enabled
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
{(onCall || remoteActive) && (
|
||||
<>
|
||||
<div
|
||||
className={
|
||||
cn(
|
||||
'cursor-pointer p-2 flex items-center',
|
||||
{[stl.disabled]: cannotCall}
|
||||
)
|
||||
}
|
||||
onClick={ () => toggleAnnotation(!annotating) }
|
||||
role="button"
|
||||
>
|
||||
<IconButton label={`Annotate`} icon={ annotating ? "pencil-stop" : "pencil"} primaryText redText={annotating} />
|
||||
</div>
|
||||
<div className={ stl.divider } />
|
||||
</>
|
||||
)}
|
||||
<div
|
||||
className={
|
||||
cn(
|
||||
'cursor-pointer p-2 flex items-center',
|
||||
{[stl.disabled]: cannotCall}
|
||||
)
|
||||
useEffect(() => {
|
||||
if (peerConnectionStatus == ConnectionStatus.Disconnected) {
|
||||
toast.info(`Live session was closed.`);
|
||||
}
|
||||
onClick={ requestReleaseRemoteControl }
|
||||
role="button"
|
||||
>
|
||||
<IconButton label={`Remote Control`} icon={ remoteActive ? "window-x" : "remote-control"} primaryText redText={remoteActive} />
|
||||
</div>
|
||||
<div className={ stl.divider } />
|
||||
|
||||
<Popup
|
||||
content={ cannotCall ? "You don’t have the permissions to perform this action." : `Call ${userId ? userId : 'User'}` }
|
||||
>
|
||||
<div
|
||||
className={
|
||||
cn(
|
||||
'cursor-pointer p-2 flex items-center',
|
||||
{[stl.disabled]: cannotCall}
|
||||
)
|
||||
}
|
||||
onClick={ onCall ? callObject?.end : confirmCall}
|
||||
role="button"
|
||||
>
|
||||
<IconButton size="small" primary={!onCall} red={onCall} label={onCall ? 'End' : 'Call'} icon="headset" />
|
||||
</div>
|
||||
</Popup>
|
||||
}, [peerConnectionStatus]);
|
||||
|
||||
<div className="fixed ml-3 left-0 top-0" style={{ zIndex: 999 }}>
|
||||
{ onCall && callObject && <ChatWindow endCall={callObject.end} userId={userId} incomeStream={incomeStream} localStream={localStream} /> }
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
function call() {
|
||||
RequestLocalStream()
|
||||
.then((lStream) => {
|
||||
setLocalStream(lStream);
|
||||
setCallObject(callPeer(lStream, setIncomeStream, lStream.stop.bind(lStream), onReject, onError));
|
||||
})
|
||||
.catch(onError);
|
||||
}
|
||||
|
||||
const confirmCall = async () => {
|
||||
if (
|
||||
await confirm({
|
||||
header: 'Start Call',
|
||||
confirmButton: 'Call',
|
||||
confirmation: `Are you sure you want to call ${userId ? userId : 'User'}?`,
|
||||
})
|
||||
) {
|
||||
call();
|
||||
}
|
||||
};
|
||||
|
||||
const onCall = calling === CallingState.OnCall || calling === CallingState.Reconnecting;
|
||||
const cannotCall = peerConnectionStatus !== ConnectionStatus.Connected || (isEnterprise && !hasPermission);
|
||||
const remoteActive = remoteControlStatus === RemoteControlStatus.Enabled;
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
{(onCall || remoteActive) && (
|
||||
<>
|
||||
<div
|
||||
className={cn('cursor-pointer p-2 flex items-center', { [stl.disabled]: cannotCall })}
|
||||
onClick={() => toggleAnnotation(!annotating)}
|
||||
role="button"
|
||||
>
|
||||
<Button
|
||||
icon={annotating ? 'pencil-stop' : 'pencil'}
|
||||
variant={annotating ? 'text-red' : 'text-primary'}
|
||||
style={{ height: '28px' }}
|
||||
>
|
||||
Annotate
|
||||
</Button>
|
||||
{/* <IconButton label={`Annotate`} icon={annotating ? 'pencil-stop' : 'pencil'} primaryText redText={annotating} /> */}
|
||||
</div>
|
||||
<div className={stl.divider} />
|
||||
</>
|
||||
)}
|
||||
<div
|
||||
className={cn('cursor-pointer p-2 flex items-center', { [stl.disabled]: cannotCall })}
|
||||
onClick={requestReleaseRemoteControl}
|
||||
role="button"
|
||||
>
|
||||
<Button
|
||||
icon={remoteActive ? 'window-x' : 'remote-control'}
|
||||
variant={remoteActive ? 'text-red' : 'text-primary'}
|
||||
style={{ height: '28px' }}
|
||||
>
|
||||
Remote Control
|
||||
</Button>
|
||||
{/* <IconButton label={`Remote Control`} icon={remoteActive ? 'window-x' : 'remote-control'} primaryText redText={remoteActive} /> */}
|
||||
</div>
|
||||
<div className={stl.divider} />
|
||||
|
||||
<Popup content={cannotCall ? 'You don’t have the permissions to perform this action.' : `Call ${userId ? userId : 'User'}`}>
|
||||
<div
|
||||
className={cn('cursor-pointer p-2 flex items-center', { [stl.disabled]: cannotCall })}
|
||||
onClick={onCall ? callObject?.end : confirmCall}
|
||||
role="button"
|
||||
>
|
||||
<Button icon="headset" variant={onCall ? 'text-red' : 'primary'} style={{ height: '28px' }}>
|
||||
{onCall ? 'End' : 'Call'}
|
||||
</Button>
|
||||
{/* <IconButton size="small" primary={!onCall} red={onCall} label={onCall ? 'End' : 'Call'} icon="headset" /> */}
|
||||
</div>
|
||||
</Popup>
|
||||
|
||||
<div className="fixed ml-3 left-0 top-0" style={{ zIndex: 999 }}>
|
||||
{onCall && callObject && (
|
||||
<ChatWindow endCall={callObject.end} userId={userId} incomeStream={incomeStream} localStream={localStream} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const con = connect(state => {
|
||||
const permissions = state.getIn([ 'user', 'account', 'permissions' ]) || []
|
||||
return {
|
||||
hasPermission: permissions.includes('ASSIST_CALL'),
|
||||
isEnterprise: state.getIn([ 'user', 'account', 'edition' ]) === 'ee',
|
||||
}
|
||||
}, { toggleChatWindow })
|
||||
const con = connect(
|
||||
(state) => {
|
||||
const permissions = state.getIn(['user', 'account', 'permissions']) || [];
|
||||
return {
|
||||
hasPermission: permissions.includes('ASSIST_CALL'),
|
||||
isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee',
|
||||
};
|
||||
},
|
||||
{ toggleChatWindow }
|
||||
);
|
||||
|
||||
export default con(connectPlayer(state => ({
|
||||
calling: state.calling,
|
||||
annotating: state.annotating,
|
||||
remoteControlStatus: state.remoteControl,
|
||||
peerConnectionStatus: state.peerConnectionStatus,
|
||||
}))(AssistActions))
|
||||
export default con(
|
||||
connectPlayer((state) => ({
|
||||
calling: state.calling,
|
||||
annotating: state.annotating,
|
||||
remoteControlStatus: state.remoteControl,
|
||||
peerConnectionStatus: state.peerConnectionStatus,
|
||||
}))(AssistActions)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
.wrapper {
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border-top-left-radius: 20px;
|
||||
border-bottom-left-radius: 20px;
|
||||
padding: 5px;
|
||||
box-shadow: -1px 1px 1px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
import React from 'react'
|
||||
import { Icon, Popup } from 'UI'
|
||||
import { connectPlayer, toggleEvents, scale } from 'Player';
|
||||
import cn from 'classnames'
|
||||
import stl from './EventsToggleButton.module.css'
|
||||
|
||||
function EventsToggleButton({ showEvents, toggleEvents }: any) {
|
||||
const toggle = () => {
|
||||
toggleEvents()
|
||||
scale()
|
||||
}
|
||||
return (
|
||||
<Popup
|
||||
content={ showEvents ? 'Hide Events' : 'Show Events' }
|
||||
size="tiny"
|
||||
inverted
|
||||
position="bottom right"
|
||||
>
|
||||
<button
|
||||
className={cn("absolute right-0 z-50", stl.wrapper)}
|
||||
onClick={toggle}
|
||||
>
|
||||
<Icon
|
||||
name={ showEvents ? 'chevron-double-right' : 'chevron-double-left' }
|
||||
size="12"
|
||||
/>
|
||||
</button>
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
|
||||
export default connectPlayer(state => ({
|
||||
showEvents: !state.showEvents
|
||||
}), { toggleEvents })(EventsToggleButton)
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './EventsToggleButton'
|
||||
|
|
@ -4,17 +4,17 @@ import { connect } from 'react-redux';
|
|||
import usePageTitle from 'App/hooks/usePageTitle';
|
||||
import { fetch as fetchSession } from 'Duck/sessions';
|
||||
import { fetchList as fetchSlackList } from 'Duck/integrations/slack';
|
||||
import { Link, NoContent, Loader } from 'UI';
|
||||
import { sessions as sessionsRoute } from 'App/routes';
|
||||
// import { Link, NoContent, Loader } from 'UI';
|
||||
// import { sessions as sessionsRoute } from 'App/routes';
|
||||
import withPermissions from 'HOCs/withPermissions'
|
||||
import LivePlayer from './LivePlayer';
|
||||
|
||||
const SESSIONS_ROUTE = sessionsRoute();
|
||||
// const SESSIONS_ROUTE = sessionsRoute();
|
||||
|
||||
function LiveSession({
|
||||
sessionId,
|
||||
loading,
|
||||
hasErrors,
|
||||
// loading,
|
||||
// hasErrors,
|
||||
session,
|
||||
fetchSession,
|
||||
fetchSlackList,
|
||||
|
|
@ -38,9 +38,9 @@ function LiveSession({
|
|||
},[ sessionId, hasSessionsPath ]);
|
||||
|
||||
return (
|
||||
<Loader className="flex-1" loading={ loading }>
|
||||
// <Loader className="flex-1" loading={ loading }>
|
||||
<LivePlayer />
|
||||
</Loader>
|
||||
// </Loader>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -50,8 +50,8 @@ export default withPermissions(['ASSIST_LIVE'], '', true)(connect((state, props)
|
|||
const hasSessiosPath = state.getIn([ 'sessions', 'sessionPath' ]).pathname.includes('/sessions');
|
||||
return {
|
||||
sessionId,
|
||||
loading: state.getIn([ 'sessions', 'loading' ]),
|
||||
hasErrors: !!state.getIn([ 'sessions', 'errors' ]),
|
||||
// loading: state.getIn([ 'sessions', 'loading' ]),
|
||||
// hasErrors: !!state.getIn([ 'sessions', 'errors' ]),
|
||||
session: state.getIn([ 'sessions', 'current' ]),
|
||||
hasSessionsPath: hasSessiosPath && !isAssist,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/Stated
|
|||
import cn from 'classnames';
|
||||
import stl from './Marker.module.css';
|
||||
import { activeTarget } from 'Player';
|
||||
import { Popup } from 'UI';
|
||||
import { Tooltip } from 'react-tippy';
|
||||
|
||||
interface Props {
|
||||
target: MarkedTarget;
|
||||
|
|
@ -21,17 +21,17 @@ export default function Marker({ target, active }: Props) {
|
|||
return (
|
||||
<div className={ cn(stl.marker, { [stl.active] : active }) } style={ style } onClick={() => activeTarget(target.index)}>
|
||||
<div className={stl.index}>{target.index + 1}</div>
|
||||
<Popup
|
||||
<Tooltip
|
||||
open={active}
|
||||
arrow
|
||||
sticky
|
||||
distance={15}
|
||||
content={(
|
||||
html={(
|
||||
<div>{target.count} Clicks</div>
|
||||
)}
|
||||
>
|
||||
<div className="absolute inset-0"></div>
|
||||
</Popup>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -116,67 +116,67 @@ function LiveSessionList(props: Props) {
|
|||
<div className="flex items-center">
|
||||
<div className="flex items-center ml-6 mr-4">
|
||||
<span className="mr-2 color-gray-medium">Sort By</span>
|
||||
<Popup
|
||||
content="No metadata available to sort"
|
||||
disabled={sortOptions.length > 0}
|
||||
>
|
||||
<div className={ cn("flex items-center", { 'disabled': sortOptions.length === 0})} >
|
||||
<Select
|
||||
plain
|
||||
right
|
||||
options={sortOptions}
|
||||
// defaultValue={sort.field}
|
||||
onChange={onSortChange}
|
||||
value={sortOptions.find((i: any) => i.value === filter.sort) || sortOptions[0]}
|
||||
/>
|
||||
<div className="mx-2" />
|
||||
<SortOrderButton onChange={(state: any) => props.applyFilter({ order: state })} sortOrder={filter.order} />
|
||||
</div>
|
||||
<Popup content="No metadata available to sort" disabled={sortOptions.length > 0}>
|
||||
<div className={cn('flex items-center', { disabled: sortOptions.length === 0 })}>
|
||||
<Select
|
||||
plain
|
||||
right
|
||||
options={sortOptions}
|
||||
// defaultValue={sort.field}
|
||||
onChange={onSortChange}
|
||||
value={sortOptions.find((i: any) => i.value === filter.sort) || sortOptions[0]}
|
||||
/>
|
||||
<div className="mx-2" />
|
||||
<SortOrderButton onChange={(state: any) => props.applyFilter({ order: state })} sortOrder={filter.order} />
|
||||
</div>
|
||||
</Popup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Loader loading={loading}>
|
||||
<NoContent
|
||||
title={'No live sessions.'}
|
||||
subtext={
|
||||
<span>
|
||||
See how to setup the{' '}
|
||||
<a target="_blank" className="link" href="https://docs.openreplay.com/plugins/assist">
|
||||
{'Assist'}
|
||||
</a>{' '}
|
||||
plugin, if you haven’t done that already.
|
||||
</span>
|
||||
}
|
||||
image={<img src="/assets/img/live-sessions.png" style={{ width: '70%', marginBottom: '30px' }} />}
|
||||
show={!loading && list.size === 0}
|
||||
>
|
||||
<div className="bg-white p-3 rounded border">
|
||||
{list.map((session) => (
|
||||
<>
|
||||
<SessionItem
|
||||
key={session.sessionId}
|
||||
session={session}
|
||||
live
|
||||
hasUserFilter={hasUserFilter}
|
||||
onUserClick={onUserClick}
|
||||
metaList={metaList}
|
||||
/>
|
||||
<div className="border-b" />
|
||||
</>
|
||||
))}
|
||||
|
||||
<div className="w-full flex items-center justify-center py-6">
|
||||
<Pagination
|
||||
page={currentPage}
|
||||
totalPages={Math.ceil(total / PER_PAGE)}
|
||||
onPageChange={(page: any) => props.updateCurrentPage(page)}
|
||||
limit={PER_PAGE}
|
||||
/>
|
||||
<div className="bg-white p-3 rounded border">
|
||||
<Loader loading={loading}>
|
||||
<NoContent
|
||||
title={'No live sessions.'}
|
||||
subtext={
|
||||
<span>
|
||||
See how to setup the{' '}
|
||||
<a target="_blank" className="link" href="https://docs.openreplay.com/plugins/assist">
|
||||
{'Assist'}
|
||||
</a>{' '}
|
||||
plugin, if you haven’t done that already.
|
||||
</span>
|
||||
}
|
||||
image={<img src="/assets/img/live-sessions.png" style={{ width: '70%', marginBottom: '30px' }} />}
|
||||
show={!loading && list.size === 0}
|
||||
>
|
||||
<div>
|
||||
{list.map((session) => (
|
||||
<>
|
||||
<SessionItem
|
||||
key={session.sessionId}
|
||||
session={session}
|
||||
live
|
||||
hasUserFilter={hasUserFilter}
|
||||
onUserClick={onUserClick}
|
||||
metaList={metaList}
|
||||
/>
|
||||
<div className="border-b" />
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</NoContent>
|
||||
</Loader>
|
||||
</NoContent>
|
||||
</Loader>
|
||||
|
||||
<div className={cn("w-full flex items-center justify-center py-6", { 'disabled' : loading})}>
|
||||
<Pagination
|
||||
page={currentPage}
|
||||
totalPages={Math.ceil(total / PER_PAGE)}
|
||||
onPageChange={(page: any) => props.updateCurrentPage(page)}
|
||||
limit={PER_PAGE}
|
||||
debounceRequest={500}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,67 +3,74 @@ import cn from 'classnames';
|
|||
import { CircularLoader, Icon } from 'UI';
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
disabled?: boolean;
|
||||
type?: 'button' | 'submit' | 'reset';
|
||||
loading?: boolean;
|
||||
icon?: string;
|
||||
[x: string]: any
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
disabled?: boolean;
|
||||
type?: 'button' | 'submit' | 'reset';
|
||||
loading?: boolean;
|
||||
icon?: string;
|
||||
[x: string]: any;
|
||||
}
|
||||
export default (props: Props) => {
|
||||
const {
|
||||
icon = '',
|
||||
className = '',
|
||||
variant = "default",
|
||||
type = "button",
|
||||
size = '',
|
||||
disabled = false,
|
||||
children,
|
||||
loading = false,
|
||||
...rest
|
||||
} = props;
|
||||
const {
|
||||
icon = '',
|
||||
className = '',
|
||||
variant = 'default',
|
||||
type = 'button',
|
||||
size = '',
|
||||
disabled = false,
|
||||
children,
|
||||
loading = false,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const classes = ['relative flex items-center h-10 px-3 rounded tracking-wide whitespace-nowrap'];
|
||||
if (variant === 'default') {
|
||||
classes.push('bg-white hover:bg-gray-lightest border border-gray-light')
|
||||
}
|
||||
const classes = ['relative flex items-center h-10 px-3 rounded tracking-wide whitespace-nowrap'];
|
||||
if (variant === 'default') {
|
||||
classes.push('bg-white hover:bg-gray-lightest border border-gray-light');
|
||||
}
|
||||
|
||||
if (variant === 'primary') {
|
||||
classes.push('bg-teal color-white hover:bg-teal-dark')
|
||||
}
|
||||
if (variant === 'primary') {
|
||||
classes.push('bg-teal color-white hover:bg-teal-dark');
|
||||
}
|
||||
|
||||
if (variant === 'text') {
|
||||
classes.push('bg-transparent color-gray-dark hover:bg-gray-lightest hover:color-gray-dark')
|
||||
}
|
||||
if (variant === 'text') {
|
||||
classes.push('bg-transparent color-gray-dark hover:bg-gray-lightest hover:color-gray-dark');
|
||||
}
|
||||
|
||||
if (variant === 'text-primary') {
|
||||
classes.push('bg-transparent color-teal hover:bg-teal-light hover:color-teal-dark')
|
||||
}
|
||||
if (variant === 'text-primary') {
|
||||
classes.push('bg-transparent color-teal hover:bg-teal-light hover:color-teal-dark');
|
||||
}
|
||||
|
||||
if (variant === 'outline') {
|
||||
classes.push('bg-white color-teal border border-teal hover:bg-teal-light')
|
||||
}
|
||||
if (variant === 'text-red') {
|
||||
classes.push('bg-transparent color-red hover:bg-teal-light');
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
classes.push('opacity-40 pointer-events-none')
|
||||
}
|
||||
if (variant === 'outline') {
|
||||
classes.push('bg-white color-teal border border-teal hover:bg-teal-light');
|
||||
}
|
||||
|
||||
const iconColor = variant === 'text' || variant === 'default' ? 'gray-dark' : 'teal';
|
||||
// console.log('children', children)
|
||||
if (disabled) {
|
||||
classes.push('opacity-40 pointer-events-none');
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
{ ...rest }
|
||||
type={type}
|
||||
className={ cn(classes, className ) }
|
||||
>
|
||||
{ icon && <Icon className={cn({ "mr-2" : children })} name={icon} color={iconColor} size="16" /> }
|
||||
{ loading && <div className="absolute flex items-center justify-center inset-0 z-1 rounded">
|
||||
<CircularLoader />
|
||||
</div> }
|
||||
<div className={cn({ 'opacity-0' : loading }, 'flex items-center')}>{children}</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
let iconColor = variant === 'text' || variant === 'default' ? 'gray-dark' : 'teal';
|
||||
if (variant === 'primary') {
|
||||
iconColor = 'white';
|
||||
}
|
||||
if (variant === 'text-red') {
|
||||
iconColor = 'red';
|
||||
}
|
||||
|
||||
return (
|
||||
<button {...rest} type={type} className={cn(classes, className)}>
|
||||
{icon && <Icon className={cn({ 'mr-2': children })} name={icon} color={iconColor} size="16" />}
|
||||
{loading && (
|
||||
<div className="absolute flex items-center justify-center inset-0 z-1 rounded">
|
||||
<CircularLoader />
|
||||
</div>
|
||||
)}
|
||||
<div className={cn({ 'opacity-0': loading }, 'flex items-center')}>{children}</div>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -33,9 +33,10 @@ export default function Pagination(props: Props) {
|
|||
return (
|
||||
<div className="flex items-center">
|
||||
<Popup
|
||||
sticky
|
||||
content="Previous Page"
|
||||
hideOnClick={true}
|
||||
// hideOnClick={true}
|
||||
animation="none"
|
||||
delay={1500}
|
||||
>
|
||||
<button
|
||||
className={cn("py-2 px-3", { "opacity-50 cursor-default": isFirstPage })}
|
||||
|
|
@ -51,16 +52,16 @@ export default function Pagination(props: Props) {
|
|||
className={cn("py-1 px-2 bg-white border border-gray-light rounded w-16", { "opacity-50 cursor-default": totalPages === 1 })}
|
||||
value={currentPage}
|
||||
min={1}
|
||||
max={totalPages}
|
||||
max={totalPages ? totalPages : 1}
|
||||
onChange={(e) => changePage(parseInt(e.target.value))}
|
||||
/>
|
||||
<span className="mx-3 color-gray-medium">of</span>
|
||||
<span >{numberWithCommas(totalPages)}</span>
|
||||
<Popup
|
||||
arrow
|
||||
sticky
|
||||
content="Next Page"
|
||||
hideOnClick={true}
|
||||
// hideOnClick={true}
|
||||
animation="none"
|
||||
delay={1500}
|
||||
>
|
||||
<button
|
||||
className={cn("py-2 px-3", { "opacity-50 cursor-default": isLastPage })}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ interface Props {
|
|||
trigger?: any
|
||||
position?: any
|
||||
className?: string
|
||||
delay?: number
|
||||
disabled?: boolean
|
||||
arrow?: boolean
|
||||
open?: boolean
|
||||
[x:string]: any;
|
||||
}
|
||||
export default ({
|
||||
|
|
@ -14,14 +18,21 @@ export default ({
|
|||
title='',
|
||||
className='',
|
||||
trigger = 'mouseenter',
|
||||
delay = 1000,
|
||||
disabled = false,
|
||||
arrow = true,
|
||||
...props
|
||||
}: Props) => (
|
||||
<Tooltip
|
||||
{ ...props }
|
||||
// {...props}
|
||||
className={className}
|
||||
trigger={trigger}
|
||||
html={props.content || props.title}
|
||||
arrow
|
||||
disabled={disabled}
|
||||
arrow={arrow}
|
||||
delay={delay}
|
||||
hideOnClick={true}
|
||||
hideOnScroll={true}
|
||||
>
|
||||
{ props.children }
|
||||
</Tooltip>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue