fix(ui): some issue/assignment refactoring
This commit is contained in:
parent
df12385e5f
commit
f6a62d835a
17 changed files with 188 additions and 179 deletions
|
|
@ -36,7 +36,7 @@ function SessionList(props: Props) {
|
|||
</div>
|
||||
<Loader loading={props.loading}>
|
||||
<NoContent
|
||||
show={!props.loading && props.list.size === 0}
|
||||
show={!props.loading && props.list.length === 0}
|
||||
title={
|
||||
<div className="flex items-center justify-center flex-col">
|
||||
<AnimatedSVG name={ICONS.NO_LIVE_SESSIONS} size={170} />
|
||||
|
|
|
|||
|
|
@ -53,5 +53,5 @@ export default connect(state => ({
|
|||
users: state.getIn(['assignments', 'users']),
|
||||
loading: state.getIn(['assignments', 'fetchAssignment', 'loading']),
|
||||
issueTypeIcons: state.getIn(['assignments', 'issueTypeIcons']),
|
||||
issuesIntegration: state.getIn([ 'issues', 'list']).first() || {},
|
||||
issuesIntegration: state.getIn([ 'issues', 'list'])[0] || {},
|
||||
}))(IssueDetails);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Form, Input, Button, CircularLoader, Loader } from 'UI';
|
||||
//import { } from 'Duck/issues';
|
||||
import { addActivity, init, edit, fetchAssignments, fetchMeta } from 'Duck/assignments';
|
||||
import Select from 'Shared/Select';
|
||||
|
||||
|
|
@ -119,7 +118,6 @@ class IssueForm extends React.PureComponent {
|
|||
selection
|
||||
name="assignee"
|
||||
options={userOptions}
|
||||
// value={ instance.assignee }
|
||||
fluid
|
||||
onChange={this.writeOption}
|
||||
placeholder="Select a user"
|
||||
|
|
@ -153,7 +151,7 @@ class IssueForm extends React.PureComponent {
|
|||
<Button
|
||||
loading={creating}
|
||||
variant="primary"
|
||||
disabled={!instance.validate()}
|
||||
disabled={!instance.isValid}
|
||||
className="float-left mr-2"
|
||||
type="submit"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Icon, Popover, Button } from 'UI';
|
||||
import { Popover, Button } from 'UI';
|
||||
import IssuesModal from './IssuesModal';
|
||||
import { fetchProjects, fetchMeta } from 'Duck/assignments';
|
||||
import stl from './issues.module.css';
|
||||
|
||||
@connect(
|
||||
(state) => ({
|
||||
|
|
@ -15,9 +14,7 @@ import stl from './issues.module.css';
|
|||
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(),
|
||||
issuesIntegration: state.getIn(['issues', 'list']) || {},
|
||||
issuesFetched: state.getIn(['issues', 'issuesFetched']),
|
||||
}),
|
||||
{ fetchMeta, fetchProjects }
|
||||
|
|
@ -58,13 +55,9 @@ class Issues extends React.Component {
|
|||
render() {
|
||||
const {
|
||||
sessionId,
|
||||
isModalDisplayed,
|
||||
projectsLoading,
|
||||
metaLoading,
|
||||
fetchIssuesLoading,
|
||||
issuesIntegration,
|
||||
} = this.props;
|
||||
const provider = issuesIntegration.provider;
|
||||
const provider = issuesIntegration.first()?.provider || '';
|
||||
|
||||
return (
|
||||
<Popover
|
||||
|
|
@ -80,13 +73,6 @@ class Issues extends React.Component {
|
|||
Create Issue
|
||||
</Button>
|
||||
</div>
|
||||
{/* <div
|
||||
className="flex items-center cursor-pointer"
|
||||
disabled={!isModalDisplayed && (metaLoading || fetchIssuesLoading || projectsLoading)}
|
||||
>
|
||||
<Icon name={`integrations/${provider === 'jira' ? 'jira' : 'github'}`} size="16" />
|
||||
<span className="ml-2 whitespace-nowrap">Create Issue</span>
|
||||
</div> */}
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import styles from './playerBlock.module.css';
|
|||
fullscreen: state.getIn(['components', 'player', 'fullscreen']),
|
||||
sessionId: state.getIn(['sessions', 'current']).sessionId,
|
||||
disabled: state.getIn(['components', 'targetDefiner', 'inspectorMode']),
|
||||
jiraConfig: state.getIn(['issues', 'list']).first(),
|
||||
jiraConfig: state.getIn(['issues', 'list'])[0],
|
||||
}))
|
||||
export default class PlayerBlock extends React.PureComponent {
|
||||
render() {
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ function SessionList(props: Props) {
|
|||
</Button>
|
||||
</div>
|
||||
}
|
||||
show={!loading && list.size === 0}
|
||||
show={!loading && list.length === 0}
|
||||
>
|
||||
{list.map((session: any) => (
|
||||
<div key={session.sessionId} className="border-b">
|
||||
|
|
@ -188,7 +188,7 @@ function SessionList(props: Props) {
|
|||
<div className="flex items-center justify-between p-5">
|
||||
<div>
|
||||
Showing <span className="font-medium">{(currentPage - 1) * pageSize + 1}</span> to{' '}
|
||||
<span className="font-medium">{(currentPage - 1) * pageSize + list.size}</span> of{' '}
|
||||
<span className="font-medium">{(currentPage - 1) * pageSize + list.length}</span> of{' '}
|
||||
<span className="font-medium">{numberWithCommas(total)}</span> sessions.
|
||||
</div>
|
||||
<Pagination
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@ import { List, Map, Set } from 'immutable';
|
|||
import Assignment from 'Types/session/assignment';
|
||||
import Activity from 'Types/session/activity';
|
||||
import withRequestState, { RequestTypes } from './requestStateCreator';
|
||||
import { createListUpdater, createItemInListUpdater } from './funcTools/tools';
|
||||
import { createListUpdater } from './funcTools/tools';
|
||||
import { editType, initType } from './funcTools/crud/types';
|
||||
import { createInit, createEdit } from './funcTools/crud';
|
||||
import IssuesType from 'Types/issue/issuesType'
|
||||
|
||||
const idKey = 'id';
|
||||
const name = 'assignment';
|
||||
|
|
@ -22,8 +21,8 @@ const INIT = initType(name);
|
|||
|
||||
const initialState = Map({
|
||||
list: List(),
|
||||
instance: Assignment(),
|
||||
activeIssue: Assignment(),
|
||||
instance: new Assignment(),
|
||||
activeIssue: new Assignment(),
|
||||
issueTypes: List(),
|
||||
issueTypeIcons: Set(),
|
||||
users: List(),
|
||||
|
|
@ -33,22 +32,23 @@ const initialState = Map({
|
|||
|
||||
const reducer = (state = initialState, action = {}) => {
|
||||
const users = state.get('users');
|
||||
var issueTypes = []
|
||||
let issueTypes = []
|
||||
switch (action.type) {
|
||||
case INIT:
|
||||
action.instance.issueType = issueTypes.length > 0 ? issueTypes[0].id : '';
|
||||
return state.set('instance', Assignment(action.instance));
|
||||
return state.set('instance', new Assignment(action.instance));
|
||||
case EDIT:
|
||||
return state.mergeIn([ 'instance' ], action.instance);
|
||||
const inst = state.get('instance')
|
||||
return state.set('instance', new Assignment({ ...inst, ...action.instance }));
|
||||
case FETCH_PROJECTS.SUCCESS:
|
||||
return state.set('projects', List(action.data)).set('projectsFetched', true);
|
||||
case FETCH_ASSIGNMENTS.SUCCESS:
|
||||
return state.set('list', List(action.data).map(Assignment));
|
||||
return state.set('list', List(action.data).map(as => new Assignment(as)));
|
||||
case FETCH_ASSIGNMENT.SUCCESS:
|
||||
return state.set('activeIssue', Assignment({ ...action.data, users}));
|
||||
return state.set('activeIssue', new Assignment({ ...action.data, users}));
|
||||
case FETCH_META.SUCCESS:
|
||||
issueTypes = action.data.issueTypes
|
||||
var issueTypeIcons = {}
|
||||
const issueTypeIcons = {}
|
||||
issueTypes.forEach(iss => {
|
||||
issueTypeIcons[iss.id] = iss.iconUrl
|
||||
})
|
||||
|
|
@ -56,12 +56,12 @@ const reducer = (state = initialState, action = {}) => {
|
|||
.set('users', List(action.data.users))
|
||||
.set('issueTypeIcons', issueTypeIcons)
|
||||
case ADD_ACTIVITY.SUCCESS:
|
||||
const instance = Assignment(action.data);
|
||||
const instance = new Assignment(action.data);
|
||||
return listUpdater(state, instance);
|
||||
case ADD_MESSAGE.SUCCESS:
|
||||
const user = users.filter(user => user.id === action.data.author).first();
|
||||
const activity = new Activity({ type: 'message', user, ...action.data,});
|
||||
return state.updateIn([ 'activeIssue', 'activities' ], list => list.push(activity));
|
||||
return state.update([ 'activeIssue' ], issue => issue.activities.push(activity));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ export default withRequestState({
|
|||
export const init = createInit(name);
|
||||
export const edit = createEdit(name);
|
||||
|
||||
export function fetchProjects(sessionId) {
|
||||
export function fetchProjects() {
|
||||
return {
|
||||
types: FETCH_PROJECTS.toArray(),
|
||||
call: client => client.get(`/integrations/issues/list_projects`)
|
||||
|
|
@ -100,13 +100,6 @@ export function fetchAssignments(sessionId) {
|
|||
}
|
||||
}
|
||||
|
||||
export function fetchAssigment(sessionId, id) {
|
||||
return {
|
||||
types: FETCH_ASSIGNMENT.toArray(),
|
||||
call: client => client.get(`/sessions/${ sessionId }/assign/${ id }`)
|
||||
}
|
||||
}
|
||||
|
||||
export function addActivity(sessionId, params) {
|
||||
const data = { ...params, assignee: params.assignee, issueType: params.issueType }
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import { createInit, createEdit } from './funcTools/crud';
|
|||
const idKey = 'id';
|
||||
const name = 'assignment';
|
||||
const listUpdater = createListUpdater(idKey);
|
||||
const itemInListUpdater = createItemInListUpdater(idKey);
|
||||
|
||||
const FETCH_ASSIGNMENTS = new RequestTypes('asignment/FETCH_ASSIGNMENTS');
|
||||
const FETCH_ISSUE = new RequestTypes('asignment/FETCH_ISSUE');
|
||||
|
|
@ -23,8 +22,8 @@ const RESET_ACTIVE_ISSUE = 'assignment/RESET_ACTIVE_ISSUE';
|
|||
|
||||
const initialState = Map({
|
||||
list: List(),
|
||||
instance: Assignment(),
|
||||
activeIssue: Assignment(),
|
||||
instance: new Assignment(),
|
||||
activeIssue: new Assignment(),
|
||||
issueTypes: List(),
|
||||
issueTypeIcons: Set(),
|
||||
users: List(),
|
||||
|
|
@ -39,9 +38,9 @@ const reducer = (state = initialState, action = {}) => {
|
|||
case FETCH_PROJECTS.SUCCESS:
|
||||
return state.set('projects', List(action.data));
|
||||
case FETCH_ASSIGNMENTS.SUCCESS:
|
||||
return state.set('list', List(action.data).map(Assignment));
|
||||
return state.set('list', action.data.map(as => new Assignment(as)));
|
||||
case ADD_ACTIVITY.SUCCESS:
|
||||
const instance = Assignment(action.data);
|
||||
const instance = new Assignment(action.data);
|
||||
return listUpdater(state, instance);
|
||||
case FETCH_META.SUCCESS:
|
||||
issueTypes = action.data.issueTypes;
|
||||
|
|
@ -53,16 +52,16 @@ const reducer = (state = initialState, action = {}) => {
|
|||
.set('users', List(action.data.users))
|
||||
.set('issueTypeIcons', issueTypeIcons)
|
||||
case FETCH_ISSUE.SUCCESS:
|
||||
return state.set('activeIssue', Assignment({ ...action.data, users}));
|
||||
return state.set('activeIssue', new Assignment({ ...action.data, users}));
|
||||
case RESET_ACTIVE_ISSUE:
|
||||
return state.set('activeIssue', Assignment());
|
||||
return state.set('activeIssue', new Assignment());
|
||||
case ADD_MESSAGE.SUCCESS:
|
||||
const user = users.filter(user => user.id === action.data.author).first();
|
||||
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 : '';
|
||||
return state.set('instance', Assignment(action.instance));
|
||||
return state.set('instance', new Assignment(action.instance));
|
||||
case EDIT:
|
||||
return state.mergeIn([ 'instance' ], action.instance);
|
||||
default:
|
||||
|
|
@ -101,13 +100,6 @@ export function fetchProjects() {
|
|||
}
|
||||
}
|
||||
|
||||
export function fetchIssue(sessionId, id) {
|
||||
return {
|
||||
types: FETCH_ISSUE.toArray(),
|
||||
call: client => client.get(`/sessions/${ sessionId }/assign/jira/${ id }`)
|
||||
}
|
||||
}
|
||||
|
||||
export function fetchMeta(projectId) {
|
||||
return {
|
||||
types: FETCH_META.toArray(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { List, Map } from 'immutable';
|
||||
import Session from 'Types/session';
|
||||
import ErrorStack from 'Types/session/errorStack';
|
||||
import { Location, InjectedEvent } from 'Types/session/event'
|
||||
import Watchdog from 'Types/watchdog';
|
||||
import { clean as cleanParams } from 'App/api_client';
|
||||
import withRequestState, { RequestTypes } from './requestStateCreator';
|
||||
|
|
@ -46,7 +47,7 @@ const defaultDateFilters = {
|
|||
};
|
||||
|
||||
const initObj = {
|
||||
list: List(),
|
||||
list: [],
|
||||
sessionIds: [],
|
||||
current: new Session(),
|
||||
total: 0,
|
||||
|
|
@ -61,7 +62,7 @@ const initObj = {
|
|||
filteredEvents: null,
|
||||
eventsQuery: '',
|
||||
showChatWindow: false,
|
||||
liveSessions: List(),
|
||||
liveSessions: [],
|
||||
visitedEvents: List(),
|
||||
insights: List(),
|
||||
insightFilters: defaultDateFilters,
|
||||
|
|
@ -76,7 +77,12 @@ const initObj = {
|
|||
|
||||
const initialState = Map(initObj);
|
||||
|
||||
const reducer = (state = initialState, action = {}) => {
|
||||
interface IAction extends Record<string, any>{
|
||||
type: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
const reducer = (state = initialState, action: IAction) => {
|
||||
switch (action.type) {
|
||||
case FETCH_ERROR_STACK.SUCCESS:
|
||||
return state.set('errorStack', List(action.data.trace).map(es => new ErrorStack(es))).set('sourcemapUploaded', action.data.sourcemapUploaded);
|
||||
|
|
@ -87,13 +93,11 @@ const reducer = (state = initialState, action = {}) => {
|
|||
const { sessions, total } = action.data;
|
||||
const list = sessions.map(s => new Session(s));
|
||||
|
||||
console.log(sessions, list, action)
|
||||
return state
|
||||
.set('list', list)
|
||||
.set('sessionIds', list.map(({ sessionId }) => sessionId).toJS())
|
||||
.set(
|
||||
'favoriteList',
|
||||
list.filter(({ favorite }) => favorite)
|
||||
)
|
||||
.set('sessionIds', list.map(({ sessionId }) => sessionId))
|
||||
.set('favoriteList', list.filter(({ favorite }) => favorite))
|
||||
.set('total', total);
|
||||
case FETCH_AUTOPLAY_LIST.SUCCESS:
|
||||
let sessionIds = state.get('sessionIds');
|
||||
|
|
@ -125,13 +129,13 @@ const reducer = (state = initialState, action = {}) => {
|
|||
const events = action.filter.events;
|
||||
const session = new Session(action.data);
|
||||
|
||||
const matching = [];
|
||||
const matching: number[] = [];
|
||||
|
||||
const visitedEvents = [];
|
||||
const tmpMap = {};
|
||||
const visitedEvents: Location[] = [];
|
||||
const tmpMap = new Set();
|
||||
session.events.forEach((event) => {
|
||||
if (event.type === 'LOCATION' && !tmpMap.hasOwnProperty(event.url)) {
|
||||
tmpMap[event.url] = event.url;
|
||||
if (event.type === 'LOCATION' && !tmpMap.has(event.url)) {
|
||||
tmpMap.add(event.url);
|
||||
visitedEvents.push(event);
|
||||
}
|
||||
});
|
||||
|
|
@ -156,7 +160,7 @@ 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(s => new Session(s)));
|
||||
return state.set('favoriteList', action.data.map(s => new Session(s)));
|
||||
case TOGGLE_FAVORITE.SUCCESS: {
|
||||
const id = action.sessionId;
|
||||
let mutableState = state
|
||||
|
|
@ -186,7 +190,7 @@ const reducer = (state = initialState, action = {}) => {
|
|||
diff = diff === 0 ? s1.startedAt - s2.startedAt : diff;
|
||||
return action.sign * diff;
|
||||
};
|
||||
return state.update('list', (list) => list.sort(comparator)).update('favoriteList', (list) => list.sort(comparator));
|
||||
return state.update('list', (list: Session[]) => list.sort(comparator)).update('favoriteList', (list: Session[]) => list.sort(comparator));
|
||||
}
|
||||
case REDEFINE_TARGET: {
|
||||
// TODO: update for list
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
import Record from 'Types/Record';
|
||||
import Activity from './activity';
|
||||
import { List } from 'immutable';
|
||||
import { DateTime } from 'luxon';
|
||||
import { validateName, notEmptyString } from 'App/validate';
|
||||
|
||||
export default Record({
|
||||
id: undefined,
|
||||
title: '',
|
||||
timestamp: undefined,
|
||||
creatorId: undefined,
|
||||
sessionId: undefined,
|
||||
projectId: '',
|
||||
siteId: undefined,
|
||||
activities: List(),
|
||||
closed: false,
|
||||
assignee: '',
|
||||
commentsCount: undefined,
|
||||
issueType: '',
|
||||
description: '',
|
||||
iconUrl: ''
|
||||
}, {
|
||||
fromJS: (assignment) => ({
|
||||
...assignment,
|
||||
timestamp: assignment.createdAt ? DateTime.fromISO(assignment.createdAt) : undefined,
|
||||
activities: assignment.comments ? List(assignment.comments).map(activity => {
|
||||
if (assignment.users) {
|
||||
activity.user = assignment.users.filter(user => user.id === activity.author).first();
|
||||
}
|
||||
return new Activity(activity)
|
||||
}) : List()
|
||||
}),
|
||||
methods: {
|
||||
validate: function() {
|
||||
return !!this.projectId && !!this.issueType &&
|
||||
notEmptyString(this.title) && notEmptyString(this.description)
|
||||
},
|
||||
toCreate: function() {
|
||||
return {
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
assignee: this.assignee,
|
||||
issueType: this.issueType
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
77
frontend/app/types/session/assignment.ts
Normal file
77
frontend/app/types/session/assignment.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import Activity, { IActivity } from './activity';
|
||||
import { DateTime } from 'luxon';
|
||||
import { notEmptyString } from 'App/validate';
|
||||
|
||||
interface IAssignment {
|
||||
id: string;
|
||||
title: string;
|
||||
timestamp: number;
|
||||
creatorId: string;
|
||||
sessionId: string;
|
||||
projectId: string;
|
||||
siteId: string;
|
||||
activities: [];
|
||||
closed: boolean;
|
||||
assignee: string;
|
||||
commentsCount: number;
|
||||
issueType: string;
|
||||
description: string;
|
||||
iconUrl: string;
|
||||
createdAt?: string;
|
||||
comments: IActivity[]
|
||||
users: { id: string }[]
|
||||
}
|
||||
|
||||
export default class Assignment {
|
||||
id: IAssignment["id"];
|
||||
title: IAssignment["title"] = '';
|
||||
timestamp: IAssignment["timestamp"];
|
||||
creatorId: IAssignment["creatorId"];
|
||||
sessionId: IAssignment["sessionId"];
|
||||
projectId: IAssignment["projectId"] = '';
|
||||
siteId: IAssignment["siteId"];
|
||||
activities: IAssignment["activities"];
|
||||
closed: IAssignment["closed"];
|
||||
assignee: IAssignment["assignee"] = '';
|
||||
commentsCount: IAssignment["commentsCount"];
|
||||
issueType: IAssignment["issueType"] = '';
|
||||
description: IAssignment["description"] = '';
|
||||
iconUrl: IAssignment["iconUrl"] = '';
|
||||
|
||||
constructor(assignment?: IAssignment) {
|
||||
if (assignment) {
|
||||
Object.assign(this, {
|
||||
...assignment,
|
||||
timestamp: assignment.createdAt ? DateTime.fromISO(assignment.createdAt) : undefined,
|
||||
activities: assignment.comments ? assignment.comments.map(activity => {
|
||||
if (assignment.users) {
|
||||
// @ts-ignore ???
|
||||
activity.user = assignment.users.filter(user => user.id === activity.author)[0];
|
||||
}
|
||||
return new Activity(activity)
|
||||
}) : []
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
toJS() {
|
||||
return this
|
||||
}
|
||||
|
||||
validate() {
|
||||
return !!this.projectId && !!this.issueType && notEmptyString(this.title) && notEmptyString(this.description)
|
||||
}
|
||||
|
||||
get isValid() {
|
||||
return !!this.projectId && !!this.issueType && notEmptyString(this.title) && notEmptyString(this.description)
|
||||
}
|
||||
|
||||
toCreate() {
|
||||
return {
|
||||
title: this.title,
|
||||
description: this.description,
|
||||
assignee: this.assignee,
|
||||
issueType: this.issueType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ function getStck0InfoString(stack: Stack) {
|
|||
return s;
|
||||
}
|
||||
|
||||
type Stack = { function: string; url: string}[]
|
||||
type Stack = { function: string; url: string }[]
|
||||
|
||||
export interface IError {
|
||||
sessionId: string
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default class ErrorStack {
|
|||
lineNo: IErrorStack["lineNo"]
|
||||
colNo: IErrorStack["colNo"]
|
||||
offset: IErrorStack["offset"]
|
||||
context:IErrorStack["context"]
|
||||
context: IErrorStack["context"]
|
||||
|
||||
constructor(es: IErrorStack) {
|
||||
Object.assign(this, {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class Input extends Event {
|
|||
}
|
||||
|
||||
|
||||
class Location extends Event {
|
||||
export class Location extends Event {
|
||||
readonly name = 'Location';
|
||||
readonly type = LOCATION;
|
||||
url: LocationEvent["url"]
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const OTHER = 'other' as const;
|
|||
function getResourceStatus(status: number, success: boolean) {
|
||||
if (status != null) return String(status);
|
||||
if (typeof success === 'boolean' || typeof success === 'number') {
|
||||
return !!success
|
||||
return !!success
|
||||
? '2xx-3xx'
|
||||
: '4xx-5xx';
|
||||
}
|
||||
|
|
@ -20,8 +20,12 @@ function getResourceStatus(status: number, success: boolean) {
|
|||
}
|
||||
|
||||
function getResourceSuccess(success: boolean, status: number) {
|
||||
if (success != null) { return !!success }
|
||||
if (status != null) { return status < 400 }
|
||||
if (success != null) {
|
||||
return !!success
|
||||
}
|
||||
if (status != null) {
|
||||
return status < 400
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +60,7 @@ interface IResource {
|
|||
success: boolean,
|
||||
score: number,
|
||||
method: string,
|
||||
request:string,
|
||||
request: string,
|
||||
response: string,
|
||||
headerSize: number,
|
||||
encodedBodySize: number,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Note } from 'App/services/NotesService'
|
|||
|
||||
const HASH_MOD = 1610612741;
|
||||
const HASH_P = 53;
|
||||
|
||||
function hashString(s: string): number {
|
||||
let mul = 1;
|
||||
let hash = 0;
|
||||
|
|
@ -192,7 +193,7 @@ export default class Session {
|
|||
const isMobile = ['console', 'mobile', 'tablet'].includes(userDeviceType);
|
||||
|
||||
const events: InjectedEvent[] = []
|
||||
const rawEvents: (EventData & { key: number})[] = []
|
||||
const rawEvents: (EventData & { key: number })[] = []
|
||||
|
||||
if (session.events?.length) {
|
||||
(session.events as EventData[]).forEach((event: EventData, k) => {
|
||||
|
|
@ -224,12 +225,13 @@ export default class Session {
|
|||
|
||||
const exceptions = (errors as IError[]).map(e => new SessionError(e)) || [];
|
||||
|
||||
const issuesList = (issues as IIssue[]).map((i, k) => new Issue({ ...i, time: i.timestamp - startedAt, key: k })) || [];
|
||||
const issuesList = (issues as IIssue[]).map(
|
||||
(i, k) => new Issue({ ...i, time: i.timestamp - startedAt, key: k })) || [];
|
||||
|
||||
const rawNotes = notes;
|
||||
const notesWithEvents = [...rawEvents, ...rawNotes].sort((a, b) => {
|
||||
// @ts-ignore just in case
|
||||
const aTs = a.timestamp || a.time;
|
||||
const aTs = a.timestamp || a.time;
|
||||
// @ts-ignore
|
||||
const bTs = b.timestamp || b.time;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,62 +9,62 @@ export const CLOUDWATCH = 'cloudwatch';
|
|||
export const ELASTICSEARCH = 'elasticsearch';
|
||||
export const SUMOLOGIC = 'sumologic';
|
||||
|
||||
export const typeList = [ OPENREPLAY, SENTRY, DATADOG, STACKDRIVER, ROLLBAR, BUGSNAG, CLOUDWATCH, ELASTICSEARCH, SUMOLOGIC ];
|
||||
export const typeList = [OPENREPLAY, SENTRY, DATADOG, STACKDRIVER, ROLLBAR, BUGSNAG, CLOUDWATCH, ELASTICSEARCH, SUMOLOGIC];
|
||||
|
||||
export function isRed(event: StackEvent) {
|
||||
if (!event.payload) return false;
|
||||
switch(event.source) {
|
||||
case SENTRY:
|
||||
return event.payload['event.type'] === 'error';
|
||||
case DATADOG:
|
||||
return true;
|
||||
case STACKDRIVER:
|
||||
return false;
|
||||
case ROLLBAR:
|
||||
return true;
|
||||
case NEWRELIC:
|
||||
return true;
|
||||
case BUGSNAG:
|
||||
return true;
|
||||
case CLOUDWATCH:
|
||||
return true;
|
||||
case SUMOLOGIC:
|
||||
return false;
|
||||
default:
|
||||
return event.level === 'error';
|
||||
}
|
||||
if (!event.payload) return false;
|
||||
switch (event.source) {
|
||||
case SENTRY:
|
||||
return event.payload['event.type'] === 'error';
|
||||
case DATADOG:
|
||||
return true;
|
||||
case STACKDRIVER:
|
||||
return false;
|
||||
case ROLLBAR:
|
||||
return true;
|
||||
case NEWRELIC:
|
||||
return true;
|
||||
case BUGSNAG:
|
||||
return true;
|
||||
case CLOUDWATCH:
|
||||
return true;
|
||||
case SUMOLOGIC:
|
||||
return false;
|
||||
default:
|
||||
return event.level === 'error';
|
||||
}
|
||||
}
|
||||
|
||||
export interface IStackEvent {
|
||||
time: number;
|
||||
timestamp: number;
|
||||
index: number;
|
||||
name: string;
|
||||
message: string;
|
||||
payload: any;
|
||||
source: any;
|
||||
level: string;
|
||||
time: number;
|
||||
timestamp: number;
|
||||
index: number;
|
||||
name: string;
|
||||
message: string;
|
||||
payload: any;
|
||||
source: any;
|
||||
level: string;
|
||||
|
||||
isRed: () => boolean;
|
||||
isRed: () => boolean;
|
||||
}
|
||||
|
||||
export default class StackEvent {
|
||||
time: IStackEvent["time"]
|
||||
index: IStackEvent["index"];
|
||||
name: IStackEvent["name"];
|
||||
message: IStackEvent["message"];
|
||||
payload: IStackEvent["payload"];
|
||||
source: IStackEvent["source"];
|
||||
level: IStackEvent["level"];
|
||||
time: IStackEvent["time"]
|
||||
index: IStackEvent["index"];
|
||||
name: IStackEvent["name"];
|
||||
message: IStackEvent["message"];
|
||||
payload: IStackEvent["payload"];
|
||||
source: IStackEvent["source"];
|
||||
level: IStackEvent["level"];
|
||||
|
||||
constructor(evt: IStackEvent) {
|
||||
Object.assign(this, {
|
||||
...evt,
|
||||
source: evt.source || OPENREPLAY
|
||||
});
|
||||
}
|
||||
constructor(evt: IStackEvent) {
|
||||
Object.assign(this, {
|
||||
...evt,
|
||||
source: evt.source || OPENREPLAY
|
||||
});
|
||||
}
|
||||
|
||||
isRed() {
|
||||
return isRed(this);
|
||||
}
|
||||
isRed() {
|
||||
return isRed(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue