diff --git a/frontend/app/components/Dashboard/Widgets/LastPerformance/LastPerformance.js b/frontend/app/components/Dashboard/Widgets/LastPerformance/LastPerformance.js
deleted file mode 100644
index e44e556aa..000000000
--- a/frontend/app/components/Dashboard/Widgets/LastPerformance/LastPerformance.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import { Loader, NoContent } from 'UI';
-import { widgetHOC, SessionLine } from '../common';
-
-@widgetHOC('sessionsPerformance', { fitContent: true })
-export default class LastFeedbacks extends React.PureComponent {
- render() {
- const { data: sessions, loading } = this.props;
- return (
-
-
- { sessions.map(({ sessionId, missedResources }) => (
-
- ))}
-
-
- );
- }
-}
diff --git a/frontend/app/components/Dashboard/Widgets/LastPerformance/index.js b/frontend/app/components/Dashboard/Widgets/LastPerformance/index.js
deleted file mode 100644
index 6563813c2..000000000
--- a/frontend/app/components/Dashboard/Widgets/LastPerformance/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from './LastPerformance';
\ No newline at end of file
diff --git a/frontend/app/components/Session/PlayerContent.js b/frontend/app/components/Session/PlayerContent.js
index c7ccfc62b..64d896455 100644
--- a/frontend/app/components/Session/PlayerContent.js
+++ b/frontend/app/components/Session/PlayerContent.js
@@ -21,7 +21,6 @@ function PlayerContent({ session, live, fullscreen, activeTab, setActiveTab }) {
const hasError = !!error
- console.log(session, 'hi')
const sessionDays = countDaysFrom(session.startedAt);
return (
diff --git a/frontend/app/components/Session/WebPlayer.tsx b/frontend/app/components/Session/WebPlayer.tsx
index de9e84036..997276a55 100644
--- a/frontend/app/components/Session/WebPlayer.tsx
+++ b/frontend/app/components/Session/WebPlayer.tsx
@@ -76,7 +76,6 @@ function WebPlayer(props: any) {
if (!contextValue.player || !session) return null;
- console.log(session)
return (
<>
diff --git a/frontend/app/duck/assignments.js b/frontend/app/duck/assignments.js
index 3abb99fb7..ecb2ca45a 100644
--- a/frontend/app/duck/assignments.js
+++ b/frontend/app/duck/assignments.js
@@ -60,7 +60,7 @@ const reducer = (state = initialState, action = {}) => {
return listUpdater(state, instance);
case ADD_MESSAGE.SUCCESS:
const user = users.filter(user => user.id === action.data.author).first();
- const activity = Activity({ type: 'message', user, ...action.data,});
+ const activity = new Activity({ type: 'message', user, ...action.data,});
return state.updateIn([ 'activeIssue', 'activities' ], list => list.push(activity));
default:
return state;
diff --git a/frontend/app/duck/issues.js b/frontend/app/duck/issues.js
index 6c2c70733..886025a16 100644
--- a/frontend/app/duck/issues.js
+++ b/frontend/app/duck/issues.js
@@ -58,7 +58,7 @@ const reducer = (state = initialState, action = {}) => {
return state.set('activeIssue', Assignment());
case ADD_MESSAGE.SUCCESS:
const user = users.filter(user => user.id === action.data.author).first();
- const activity = Activity({ type: 'message', user, ...action.data,});
+ const activity = new Activity({ type: 'message', user, ...action.data,});
return state.updateIn([ 'activeIssue', 'activities' ], list => list.push(activity));
case INIT:
action.instance.issueType = issueTypes.length > 0 ? issueTypes[0].id : '';
diff --git a/frontend/app/duck/sessions.js b/frontend/app/duck/sessions.ts
similarity index 85%
rename from frontend/app/duck/sessions.js
rename to frontend/app/duck/sessions.ts
index 6f015f510..7a4ebd29d 100644
--- a/frontend/app/duck/sessions.js
+++ b/frontend/app/duck/sessions.ts
@@ -9,7 +9,6 @@ import { LAST_7_DAYS } from 'Types/app/period';
import { getDateRangeFromValue } from 'App/dateRange';
const name = 'sessions';
-const INIT = 'sessions/INIT';
const FETCH_LIST = new RequestTypes('sessions/FETCH_LIST');
const FETCH_AUTOPLAY_LIST = new RequestTypes('sessions/FETCH_AUTOPLAY_LIST');
const FETCH = new RequestTypes('sessions/FETCH');
@@ -46,7 +45,7 @@ const defaultDateFilters = {
endDate: range.end.unix() * 1000,
};
-const initialState = Map({
+const initObj = {
list: List(),
sessionIds: [],
current: new Session(),
@@ -73,22 +72,20 @@ const initialState = Map({
lastPlayedSessionId: null,
timeLineTooltip: { time: 0, offset: 0, isVisible: false, timeStr: '' },
createNoteTooltip: { time: 0, isVisible: false, isEdit: false, note: null },
-});
+}
+
+const initialState = Map(initObj);
const reducer = (state = initialState, action = {}) => {
switch (action.type) {
- case INIT:
- return state.set('current', Session(action.session));
- // case FETCH_LIST.REQUEST:
- // return action.clear ? state.set('list', List()) : state;
case FETCH_ERROR_STACK.SUCCESS:
- return state.set('errorStack', List(action.data.trace).map(ErrorStack)).set('sourcemapUploaded', action.data.sourcemapUploaded);
+ return state.set('errorStack', List(action.data.trace).map(es => new ErrorStack(es))).set('sourcemapUploaded', action.data.sourcemapUploaded);
case FETCH_LIVE_LIST.SUCCESS:
- const liveList = List(action.data.sessions).map((s) => new Session({ ...s, live: true }));
+ const liveList = action.data.sessions.map((s) => new Session({ ...s, live: true }));
return state.set('liveSessions', liveList);
case FETCH_LIST.SUCCESS:
const { sessions, total } = action.data;
- const list = List(sessions).map(Session);
+ const list = sessions.map(s => new Session(s));
return state
.set('list', list)
@@ -126,8 +123,6 @@ const reducer = (state = initialState, action = {}) => {
case FETCH.SUCCESS: {
// TODO: more common.. or TEMP
const events = action.filter.events;
- // const filters = action.filter.filters;
- const current = state.get('list').find(({ sessionId }) => sessionId === action.data.sessionId) || new Session();
const session = new Session(action.data);
const matching = [];
@@ -161,20 +156,27 @@ const reducer = (state = initialState, action = {}) => {
.set('host', visitedEvents[0] && visitedEvents[0].host);
}
case FETCH_FAVORITE_LIST.SUCCESS:
- return state.set('favoriteList', List(action.data).map(Session));
+ return state.set('favoriteList', List(action.data).map(s => new Session(s)));
case TOGGLE_FAVORITE.SUCCESS: {
const id = action.sessionId;
- const session = state.get('list').find(({ sessionId }) => sessionId === id);
+ let mutableState = state
+ const list = state.get('list') as unknown as Session[]
+ const sessionIdx = list.findIndex(({ sessionId }) => sessionId === id);
+ const session = list[sessionIdx]
+ const current = state.get('current') as unknown as Session;
const wasInFavorite = state.get('favoriteList').findIndex(({ sessionId }) => sessionId === id) > -1;
if (session && !wasInFavorite) {
session.favorite = true
+ mutableState = mutableState.updateIn(['list', sessionIdx], () => session)
}
- return state
- // TODO returns bool here???
- .update('current', (currentSession) => (currentSession.sessionId === id ? (currentSession.favorite = !wasInFavorite) : currentSession))
- .update('list', (list) => list.map((listSession) => (listSession.sessionId === id ? (listSession.favorite = !wasInFavorite) : listSession)))
- .update('favoriteList', (list) => session ?
+ if (current.sessionId === id) {
+ mutableState = mutableState.update('current',
+ (s: Session) => ({ ...s, favorite: !wasInFavorite})
+ )
+ }
+ return mutableState
+ .update('favoriteList', (list: Session[]) => session ?
wasInFavorite ? list.filter(({ sessionId }) => sessionId !== id) : list.push(session) : list
);
}
@@ -217,8 +219,16 @@ const reducer = (state = initialState, action = {}) => {
case SET_EDIT_NOTE_TOOLTIP:
return state.set('createNoteTooltip', action.noteTooltip);
case FILTER_OUT_NOTE:
- return state.updateIn(['current', 'notesWithEvents'], (list) =>
- list.filter(evt => !evt.noteId || evt.noteId !== action.noteId)
+ return state.updateIn(['current'],
+ (session: Session) => ({
+ ...session,
+ notesWithEvents: session.notesWithEvents.filter(item => {
+ if ('noteId' in item) {
+ return item.noteId !== action.noteId
+ }
+ return true
+ })
+ })
)
case ADD_NOTE:
return state.updateIn(['current', 'notesWithEvents'], (list) =>
@@ -230,25 +240,21 @@ const reducer = (state = initialState, action = {}) => {
})
)
case UPDATE_NOTE:
- const index = state.getIn(['current', 'notesWithEvents']).findIndex(item => item.noteId === action.note.noteId)
- return state.setIn(['current', 'notesWithEvents', index], action.note)
+ const noteIndex = state.getIn(['current']).notesWithEvents.findIndex(item => item.noteId === action.note.noteId)
+ return state.setIn(['current', 'notesWithEvents', noteIndex], action.note)
case SET_SESSION_PATH:
return state.set('sessionPath', action.path);
case LAST_PLAYED_SESSION_ID:
- return updateListItem(state, action.sessionId, { viewed: true }).set('lastPlayedSessionId', action.sessionId);
+ const sessionList = state.get('list') as unknown as Session[];
+ const sIndex = sessionList.findIndex(({ sessionId }) => sessionId === action.sessionId);
+ if (sIndex === -1) return state;
+
+ return state.updateIn(['list', sIndex], (session: Session) => ({ ...session, viewed: true }));
default:
return state;
}
};
-function updateListItem(state, sourceSessionId, instance) {
- const list = state.get('list');
- const index = list.findIndex(({ sessionId }) => sessionId === sourceSessionId);
- if (index === -1) return state;
-
- return state.updateIn(['list', index], (session) => session.merge(instance));
-}
-
export default withRequestState(
{
_: [FETCH, FETCH_LIST],
@@ -261,13 +267,6 @@ export default withRequestState(
reducer
);
-function init(session) {
- return {
- type: INIT,
- session,
- };
-}
-
export const fetchList =
(params = {}, force = false) =>
(dispatch) => {
@@ -324,13 +323,6 @@ export function toggleFavorite(sessionId) {
};
}
-export function fetchFavoriteList() {
- return {
- types: FETCH_FAVORITE_LIST.toArray(),
- call: (client) => client.get('/sessions/favorite'),
- };
-}
-
export function fetchInsights(params) {
return {
types: FETCH_INSIGHTS.toArray(),
@@ -361,13 +353,6 @@ export function sort(sortKey, sign = 1, listName = 'list') {
};
}
-export function redefineTarget(target) {
- return {
- type: REDEFINE_TARGET,
- target,
- };
-}
-
export const setAutoplayValues = (sessionId) => {
return {
type: SET_AUTOPLAY_VALUES,
diff --git a/frontend/app/types/session/activity.js b/frontend/app/types/session/activity.js
deleted file mode 100644
index bb9be45fa..000000000
--- a/frontend/app/types/session/activity.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import Record from 'Types/Record';
-import { DateTime } from 'luxon';
-
-const ASSIGN = 'assign';
-const MESSAGE = 'message';
-const OPEN = 'open';
-const CLOSE = 'close';
-
-export const TYPES = { ASSIGN, MESSAGE, OPEN, CLOSE };
-
-const Activity = Record({
- id: undefined,
- type: '',
- author: '',
- // thread_id: undefined,
- createdAt: undefined,
- // assigned_to: undefined,
- // user_id: undefined,
- message: '',
- user: ''
-})
-
-// const Assign = Activity.extend({
-// type: ASSIGN,
-// })
-
-// const Message = Activity.extend({
-// type: MESSAGE,
-// })
-
-// const Open = Activity.extend({
-// type: OPEN,
-// })
-
-// const Close = Activity.extend({
-// type: CLOSE,
-// })
-
-// const Open = Activity.extend({
-// type: OPEN,
-// })
-
-export default function(activity = {}) {
- // if (activity.type === ASSIGN) return Assign(activity);
- // if (activity.type === MESSAGE) return Message(activity);
- // if (activity.type === OPEN) return Open(activity);
- // if (activity.type === CLOSE) return Close(activity);
- return Activity({
- ...activity,
- createdAt: activity.createdAt ? DateTime.fromMillis(activity.createdAt, {}).toUTC() : undefined,
- });
-}
-
diff --git a/frontend/app/types/session/activity.ts b/frontend/app/types/session/activity.ts
new file mode 100644
index 000000000..97e5e2a5c
--- /dev/null
+++ b/frontend/app/types/session/activity.ts
@@ -0,0 +1,49 @@
+import { DateTime } from 'luxon';
+
+const ASSIGN = 'assign';
+const MESSAGE = 'message';
+const OPEN = 'open';
+const CLOSE = 'close';
+
+export const TYPES = { ASSIGN, MESSAGE, OPEN, CLOSE } as const;
+
+
+type TypeKeys = keyof typeof TYPES
+type TypeValues = typeof TYPES[TypeKeys]
+
+
+export interface IActivity {
+ id: string;
+ type: TypeValues;
+ author: string;
+ createdAt: number;
+ message: string;
+ user: string;
+}
+
+export default class Activity {
+ id: IActivity["id"];
+ type: IActivity["type"];
+ author: IActivity["author"];
+ createdAt?: DateTime;
+ message: IActivity["message"];
+ user: IActivity["user"];
+
+ constructor(activity?: IActivity) {
+ if (activity) {
+ Object.assign(this, {
+ ...activity,
+ createdAt: activity.createdAt ? DateTime.fromMillis(activity.createdAt, {}).toUTC() : undefined,
+ })
+ } else {
+ Object.assign(this, {
+ id: undefined,
+ type: '',
+ author: '',
+ createdAt: undefined,
+ message: '',
+ user: ''
+ })
+ }
+ }
+}
diff --git a/frontend/app/types/session/assignment.js b/frontend/app/types/session/assignment.js
index 0c599c85c..ee3e790a6 100644
--- a/frontend/app/types/session/assignment.js
+++ b/frontend/app/types/session/assignment.js
@@ -27,7 +27,7 @@ export default Record({
if (assignment.users) {
activity.user = assignment.users.filter(user => user.id === activity.author).first();
}
- return Activity(activity)
+ return new Activity(activity)
}) : List()
}),
methods: {
diff --git a/frontend/app/types/session/customField.js b/frontend/app/types/session/customField.js
deleted file mode 100644
index 79f26b914..000000000
--- a/frontend/app/types/session/customField.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import CustomField from 'Types/customField';
-
-export default CustomField.extend({
- value: undefined,
-});
\ No newline at end of file
diff --git a/frontend/app/types/session/errorStack.js b/frontend/app/types/session/errorStack.js
deleted file mode 100644
index b92610229..000000000
--- a/frontend/app/types/session/errorStack.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import Record from 'Types/Record';
-
-export default Record({
- // url: undefined,
- absPath: undefined,
- filename: undefined,
- // args: [],
- function: undefined,
- lineNo: undefined,
- colNo: undefined,
- offset: 0,
- context: undefined
-});
diff --git a/frontend/app/types/session/errorStack.ts b/frontend/app/types/session/errorStack.ts
new file mode 100644
index 000000000..c0fac6e83
--- /dev/null
+++ b/frontend/app/types/session/errorStack.ts
@@ -0,0 +1,26 @@
+interface IErrorStack {
+ absPath?: string,
+ filename?: string,
+ function?: string,
+ lineNo?: number,
+ colNo?: number,
+ offset?: number,
+ context?: string
+}
+
+export default class ErrorStack {
+ absPath: IErrorStack["absPath"]
+ filename: IErrorStack["filename"]
+ function: IErrorStack["function"]
+ lineNo: IErrorStack["lineNo"]
+ colNo: IErrorStack["colNo"]
+ offset: IErrorStack["offset"]
+ context:IErrorStack["context"]
+
+ constructor(es: IErrorStack) {
+ Object.assign(this, {
+ ...es,
+ offset: es.offset || 0,
+ })
+ }
+}
\ No newline at end of file
diff --git a/frontend/app/types/session/reduxAction.js b/frontend/app/types/session/reduxAction.js
deleted file mode 100644
index e03ab9ce9..000000000
--- a/frontend/app/types/session/reduxAction.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import Record from 'Types/Record';
-
-export default Record({
- time: undefined,
- index: undefined,
- action: {},
- state: undefined,
- diff: [],
- duration: undefined,
-});
-
-
diff --git a/frontend/app/types/session/session.ts b/frontend/app/types/session/session.ts
index 298ec4fa0..337a7864a 100644
--- a/frontend/app/types/session/session.ts
+++ b/frontend/app/types/session/session.ts
@@ -38,7 +38,10 @@ export interface ISession {
filterId?: string,
domURL: string[],
devtoolsURL: string[],
- mobsUrl: string[], // @depricated
+ /**
+ * @deprecated
+ */
+ mobsUrl: string[],
userBrowser: string,
userBrowserVersion: string,
userCountry: string,
@@ -71,7 +74,7 @@ export interface ISession {
isCallActive?: boolean,
agentToken: string,
notes: Note[],
- notesWithEvents: Note[] | InjectedEvent[],
+ notesWithEvents: Array,
fileKey: string,
platform: string,
projectId: string,
@@ -103,6 +106,7 @@ const emptyValues = {
metadata: {},
startedAt: 0,
}
+
export default class Session {
sessionId: ISession["sessionId"]
pageTitle: ISession["pageTitle"]
@@ -116,13 +120,15 @@ export default class Session {
events: ISession["events"]
stackEvents: ISession["stackEvents"]
resources: ISession["resources"]
- missedResources: ISession["missedResources"]
metadata: ISession["metadata"]
favorite: ISession["favorite"]
filterId?: ISession["filterId"]
domURL: ISession["domURL"]
devtoolsURL: ISession["devtoolsURL"]
- mobsUrl: ISession["mobsUrl"] // @depricated
+ /**
+ * @deprecated
+ */
+ mobsUrl: ISession["mobsUrl"]
userBrowser: ISession["userBrowser"]
userBrowserVersion: ISession["userBrowserVersion"]
userCountry: ISession["userCountry"]
@@ -222,8 +228,10 @@ export default class Session {
const rawNotes = notes;
const notesWithEvents = [...rawEvents, ...rawNotes].sort((a, b) => {
- const aTs = a.time || a.timestamp;
- const bTs = b.time || b.timestamp;
+ // @ts-ignore just in case
+ const aTs = a.timestamp || a.time;
+ // @ts-ignore
+ const bTs = b.timestamp || b.time;
return aTs - bTs;
}) || [];
diff --git a/frontend/app/types/session/stackEvent.ts b/frontend/app/types/session/stackEvent.ts
index d1c4b7b09..89dc1a7cc 100644
--- a/frontend/app/types/session/stackEvent.ts
+++ b/frontend/app/types/session/stackEvent.ts
@@ -11,7 +11,7 @@ export const SUMOLOGIC = 'sumologic';
export const typeList = [ OPENREPLAY, SENTRY, DATADOG, STACKDRIVER, ROLLBAR, BUGSNAG, CLOUDWATCH, ELASTICSEARCH, SUMOLOGIC ];
-export function isRed(event) {
+export function isRed(event: StackEvent) {
if (!event.payload) return false;
switch(event.source) {
case SENTRY:
@@ -31,7 +31,7 @@ export function isRed(event) {
case SUMOLOGIC:
return false;
default:
- return event.level==='error';
+ return event.level === 'error';
}
}