diff --git a/frontend/app/components/Session_/Player/Controls/Timeline.tsx b/frontend/app/components/Session_/Player/Controls/Timeline.tsx
index 32e6d35eb..5a47b1df2 100644
--- a/frontend/app/components/Session_/Player/Controls/Timeline.tsx
+++ b/frontend/app/components/Session_/Player/Controls/Timeline.tsx
@@ -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,
};
diff --git a/frontend/app/components/Session_/Player/Controls/components/TimeTooltip.tsx b/frontend/app/components/Session_/Player/Controls/components/TimeTooltip.tsx
index e1be98622..5c4d19c0d 100644
--- a/frontend/app/components/Session_/Player/Controls/components/TimeTooltip.tsx
+++ b/frontend/app/components/Session_/Player/Controls/components/TimeTooltip.tsx
@@ -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 (
- {!time ? 'Loading' : duration}
+ {!time ? 'Loading' : time}
);
}
diff --git a/frontend/app/components/Session_/Subheader.js b/frontend/app/components/Session_/Subheader.js
index be7679fd5..45d5540bb 100644
--- a/frontend/app/components/Session_/Subheader.js
+++ b/frontend/app/components/Session_/Subheader.js
@@ -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(, { right: true });
};
+ const timeStr = settingsStore.isUniTs ? 'Local Time' : 'Relative Timestamp'
+ const onFormatCh = (e) => {
+ e.stopPropagation();
+ e.preventDefault();
+ settingsStore.toggleTimeFormat()
+ }
return (
+
+ {!isAssist && (
+
+ {timeStr}
+
)}
{location && (
+ 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(
-
0} />,
+ 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));
diff --git a/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.tsx b/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.tsx
index a9f90e723..be5386eab 100644
--- a/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.tsx
+++ b/frontend/app/components/shared/FetchDetailsModal/FetchDetailsModal.tsx
@@ -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 (
Network Request
-
+
{isXHR && !fetchPresented &&
}
{isXHR &&
}
diff --git a/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/FetchBasicDetails.tsx b/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/FetchBasicDetails.tsx
index 49e16c00f..94aadfb1d 100644
--- a/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/FetchBasicDetails.tsx
+++ b/frontend/app/components/shared/FetchDetailsModal/components/FetchBasicDetails/FetchBasicDetails.tsx
@@ -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 && (
-
Time
+
Duration
{_duration} ms
)}
+
+ {timestamp && (
+
+
Time
+
+ {timestamp}
+
+
+
+ )}
);
}
diff --git a/frontend/app/mstore/notesStore.ts b/frontend/app/mstore/notesStore.ts
index 1cb041049..ea52cb2e7 100644
--- a/frontend/app/mstore/notesStore.ts
+++ b/frontend/app/mstore/notesStore.ts
@@ -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 {
diff --git a/frontend/app/mstore/settingsStore.ts b/frontend/app/mstore/settingsStore.ts
index 45cb9610c..b05c9ce58 100644
--- a/frontend/app/mstore/settingsStore.ts
+++ b/frontend/app/mstore/settingsStore.ts
@@ -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())