change(ui): allow changing from relative timest to actual time
This commit is contained in:
parent
91b4b3b924
commit
ea69792159
8 changed files with 58 additions and 20 deletions
|
|
@ -11,7 +11,7 @@ import TooltipContainer from './components/TooltipContainer';
|
|||
import { PlayerContext } from 'App/components/Session/playerContext';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
||||
import { DateTime, Duration } from 'luxon';
|
||||
|
||||
function getTimelinePosition(value: number, scale: number) {
|
||||
const pos = value * scale;
|
||||
|
|
@ -22,7 +22,7 @@ function getTimelinePosition(value: number, scale: number) {
|
|||
function Timeline(props) {
|
||||
const { player, store } = useContext(PlayerContext)
|
||||
const [wasPlaying, setWasPlaying] = useState(false)
|
||||
const { notesStore } = useStore();
|
||||
const { notesStore, settingsStore } = useStore();
|
||||
const {
|
||||
playing,
|
||||
time,
|
||||
|
|
@ -89,20 +89,21 @@ function Timeline(props) {
|
|||
return props.tooltipVisible && hideTimeTooltip();
|
||||
}
|
||||
|
||||
|
||||
let timeLineTooltip;
|
||||
|
||||
if (live) {
|
||||
const [time, duration] = getLiveTime(e);
|
||||
timeLineTooltip = {
|
||||
time: duration - time,
|
||||
time: Duration.fromMillis(duration - time).toFormat(`-mm:ss`),
|
||||
offset: e.nativeEvent.offsetX,
|
||||
isVisible: true,
|
||||
};
|
||||
} else {
|
||||
const time = getTime(e);
|
||||
timeLineTooltip = {
|
||||
time: time,
|
||||
time: !settingsStore.isUniTs
|
||||
? Duration.fromMillis(time).toFormat(`mm:ss`)
|
||||
: DateTime.fromMillis(props.startedAt + time).toFormat(`hh:mm:ss a`),
|
||||
offset: e.nativeEvent.offsetX,
|
||||
isVisible: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,26 +8,25 @@ interface Props {
|
|||
time: number;
|
||||
offset: number;
|
||||
isVisible: boolean;
|
||||
liveTimeTravel: boolean;
|
||||
}
|
||||
|
||||
function TimeTooltip({
|
||||
time,
|
||||
offset,
|
||||
isVisible,
|
||||
liveTimeTravel,
|
||||
}: Props) {
|
||||
const duration = Duration.fromMillis(time).toFormat(`${liveTimeTravel ? '-' : ''}mm:ss`);
|
||||
return (
|
||||
<div
|
||||
className={stl.timeTooltip}
|
||||
style={{
|
||||
top: -30,
|
||||
left: offset - 20,
|
||||
left: offset,
|
||||
display: isVisible ? 'block' : 'none',
|
||||
transform: 'translateX(-50%)',
|
||||
whiteSpace: 'nowrap',
|
||||
}}
|
||||
>
|
||||
{!time ? 'Loading' : duration}
|
||||
{!time ? 'Loading' : time}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ import { useModal } from 'App/components/Modal';
|
|||
import BugReportModal from './BugReport/BugReportModal';
|
||||
import { PlayerContext } from 'App/components/Session/playerContext';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import AutoplayToggle from 'Shared/AutoplayToggle';
|
||||
import { Toggler } from 'UI';
|
||||
|
||||
function SubHeader(props) {
|
||||
const { player, store } = React.useContext(PlayerContext)
|
||||
|
|
@ -26,6 +28,7 @@ function SubHeader(props) {
|
|||
eventList: eventsList,
|
||||
endTime,
|
||||
} = store.get()
|
||||
const { settingsStore } = useStore()
|
||||
|
||||
const mappedResourceList = resourceList
|
||||
.filter((r) => r.isRed() || r.isYellow())
|
||||
|
|
@ -53,8 +56,19 @@ function SubHeader(props) {
|
|||
showModal(<BugReportModal width={width} height={height} xrayProps={xrayProps} hideModal={hideModal} />, { right: true });
|
||||
};
|
||||
|
||||
const timeStr = settingsStore.isUniTs ? 'Local Time' : 'Relative Timestamp'
|
||||
const onFormatCh = (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
settingsStore.toggleTimeFormat()
|
||||
}
|
||||
return (
|
||||
<div className="w-full px-4 py-2 flex items-center border-b">
|
||||
|
||||
{!isAssist && (<div onClick={onFormatCh} className="cursor-pointer color-gray-medium text-sm p-1 flex items-center gap-2 mr-2 hover:bg-gray-light-shade rounded-md">
|
||||
<Toggler plain name="sessionsLive" checked={settingsStore.isUniTs} />
|
||||
<span>{timeStr}</span>
|
||||
</div>)}
|
||||
{location && (
|
||||
<div
|
||||
className="flex items-center cursor-pointer color-gray-medium text-sm p-1 hover:bg-gray-light-shade rounded-md"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { useModal } from 'App/components/Modal';
|
|||
import FetchDetailsModal from 'Shared/FetchDetailsModal';
|
||||
import { PlayerContext } from 'App/components/Session/playerContext';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
||||
import { connect } from 'react-redux'
|
||||
import TimeTable from '../TimeTable';
|
||||
import BottomBlock from '../BottomBlock';
|
||||
import InfoLine from '../BottomBlock/InfoLine';
|
||||
|
|
@ -127,7 +127,7 @@ export function renderDuration(r: any) {
|
|||
);
|
||||
}
|
||||
|
||||
function NetworkPanel() {
|
||||
function NetworkPanel({ startedAt }: { startedAt: number }) {
|
||||
const { player, store } = React.useContext(PlayerContext)
|
||||
|
||||
const {
|
||||
|
|
@ -152,7 +152,7 @@ function NetworkPanel() {
|
|||
const activeTab = devTools[INDEX_KEY].activeTab;
|
||||
const activeIndex = devTools[INDEX_KEY].index;
|
||||
|
||||
const list = useMemo(() =>
|
||||
const list = useMemo(() =>
|
||||
resourceList.filter(res => !fetchList.some(ft => {
|
||||
if (res.url !== ft.url) { return false }
|
||||
if (Math.abs(res.time - ft.time) > 200) { return false } // TODO: find good epsilons
|
||||
|
|
@ -228,7 +228,7 @@ function NetworkPanel() {
|
|||
const showDetailsModal = (item: any) => {
|
||||
setIsDetailsModalActive(true)
|
||||
showModal(
|
||||
<FetchDetailsModal resource={item} rows={filteredList} fetchPresented={fetchList.length > 0} />,
|
||||
<FetchDetailsModal time={item.time + startedAt} resource={item} rows={filteredList} fetchPresented={fetchList.length > 0} />,
|
||||
{
|
||||
right: true,
|
||||
onClose: () => {
|
||||
|
|
@ -366,7 +366,7 @@ function NetworkPanel() {
|
|||
hidden: activeTab === XHR,
|
||||
},
|
||||
{
|
||||
label: 'Time',
|
||||
label: 'Duration',
|
||||
width: 80,
|
||||
dataKey: 'duration',
|
||||
render: renderDuration,
|
||||
|
|
@ -380,4 +380,6 @@ function NetworkPanel() {
|
|||
);
|
||||
}
|
||||
|
||||
export default observer(NetworkPanel);
|
||||
export default connect((state: any) => ({
|
||||
startedAt: state.getIn(['sessions', 'current', 'startedAt']),
|
||||
}))(observer(NetworkPanel));
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@ import FetchPluginMessage from './components/FetchPluginMessage';
|
|||
import { TYPES } from 'Types/session/resource';
|
||||
import FetchTabs from './components/FetchTabs/FetchTabs';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
interface Props {
|
||||
resource: any;
|
||||
time?: number;
|
||||
rows?: any;
|
||||
fetchPresented?: boolean;
|
||||
}
|
||||
|
|
@ -47,7 +49,7 @@ function FetchDetailsModal(props: Props) {
|
|||
return (
|
||||
<div className="bg-white p-5 h-screen overflow-y-auto" style={{ width: '500px' }}>
|
||||
<h5 className="mb-2 text-2xl">Network Request</h5>
|
||||
<FetchBasicDetails resource={resource} />
|
||||
<FetchBasicDetails resource={resource} timestamp={props.time ? DateTime.fromMillis(props.time).toFormat(`hh:mm:ss a`) : undefined} />
|
||||
|
||||
{isXHR && !fetchPresented && <FetchPluginMessage />}
|
||||
{isXHR && <FetchTabs resource={resource} />}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import cn from 'classnames';
|
|||
|
||||
interface Props {
|
||||
resource: any;
|
||||
timestamp?: string;
|
||||
}
|
||||
function FetchBasicDetails({ resource }: Props) {
|
||||
function FetchBasicDetails({ resource, timestamp }: Props) {
|
||||
const _duration = parseInt(resource.duration);
|
||||
const text = useMemo(() => {
|
||||
if (resource.url.length > 50) {
|
||||
|
|
@ -69,12 +70,22 @@ function FetchBasicDetails({ resource }: Props) {
|
|||
|
||||
{!!_duration && (
|
||||
<div className="flex items-center py-1">
|
||||
<div className="font-medium">Time</div>
|
||||
<div className="font-medium">Duration</div>
|
||||
<div className="rounded bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip">
|
||||
{_duration} ms
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{timestamp && (
|
||||
<div className="flex items-center py-1">
|
||||
<div className="font-medium">Time</div>
|
||||
<div className="rounded bg-active-blue px-2 py-1 ml-2 whitespace-nowrap overflow-hidden text-clip">
|
||||
{timestamp}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default class NotesStore {
|
|||
this.loading = true
|
||||
try {
|
||||
const notes = await notesService.getNotesBySessionId(sessionId)
|
||||
this.sessionNotes = notes
|
||||
this.setNotes(notes)
|
||||
return notes;
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
|
|
@ -53,6 +53,10 @@ export default class NotesStore {
|
|||
}
|
||||
}
|
||||
|
||||
setNotes(notes: Note[]) {
|
||||
this.sessionNotes = notes
|
||||
}
|
||||
|
||||
async addNote(sessionId: string, note: WriteNote) {
|
||||
this.loading = true
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export default class SettingsStore {
|
|||
sessionSettings: SessionSettings = new SessionSettings()
|
||||
captureRateFetched: boolean = false;
|
||||
limits: any = null;
|
||||
isUniTs = false;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
|
|
@ -15,6 +16,10 @@ export default class SettingsStore {
|
|||
})
|
||||
}
|
||||
|
||||
toggleTimeFormat = () => {
|
||||
this.isUniTs = !this.isUniTs
|
||||
}
|
||||
|
||||
saveCaptureRate(data: any) {
|
||||
return sessionService.saveCaptureRate(data)
|
||||
.then(data => data.json())
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue