* ci(deployment): injecting secrets Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * fix: typo * feat(installation): Enterprise license check * fix(install): reset ee cli args Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * Fix typo * Update README.md * feat (tracker-axios): init plugin * fix (tracker-axios): version patch * Fixed alert's unknown metrics handler * fix (tracker-mobx): dev-dependencies and updated package-lock * feat: APIs for user session data deleteion - wip * fix: alert metric value of performance.speed_index * Build and deploy scripts for enterprise edition (#13) * feat(installation): enterprise installation * chore(install): enabling ansible gather_facts Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(install): quotes for enterprise key Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(installation): enterprise install dbs Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(install): rename yaml * chore(install): change image tag Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(install): License key variable added * chore(deployment): Injecting enterprise license key in workers. * chore(install): remove deprecated files * chore(install): make domain_name mandatory in vars.yaml Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(actions): ee workers Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * feat(install): use local docker instead of crictl You can use the images built in the local machine, in installation, without putting that in any external registry. Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * feat: APIs for user session data deleteion * feat: prefix deleted mobs with DEL_ * feat: schedules to delete mobs * chore(ci): fix ee build Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * feat(build): passing build args to internal scripts Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(install): moving kafka topic creation at the end Kafka pods usually takes time to be active. Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(install): removing auth service. * chore(install): Adding rancher for cluster management * chore(install): proper name for alerts template * separate requirements and clean up * feat (frontend): typescript support * feat (tracker): 3.0.4: maintain baseURL & connAttempt options * feat(api): changed license validation * feat(api): ee-license fix for unprovided value * feat(api): fixed ee-signup cursor * feat(api): FOS fix replay-mob issue * feat(api): ee log ch-resources query * chore(ci): change openreplay-cli with kube-install.sh Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * ci(actions): change ee naming * feat(api): removed ch-logs * feat(install): injecting ee variables only on ee installation. Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * chore(install): remove licence key from ee Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * fix(install): ch values for chalice * feat(clickhouse): moved creation scripts to EE folder * fix (backend-ee): disable ios tables so far * chore(install): remove deprecated mandatory variables. Signed-off-by: Rajesh Rajendran <rjshrjndrn@gmail.com> * feat(api): remove duplicate files & changed signup * fix(backend-ee): ch prepare after commit * fix(backend-ee): syntax * feat(api): added missing EE tenant column * fix(scripts-ee): correct default clickhouse host * feat(api): changed version_number location * feat(api): ee log ch-errors query * feat(api): ee fix ch-errors query * feat: skip to issue button (#23) * feat(api): 🐛 ee fix ambiguous ch-error query & accounts endpoint * Feature: Autoplay Sessions (#22) * feat: autoplay sessions * change: removed unused import * auto play filter by tab * feat(api): changed JWT authorizer & API_KEY authorizer & fix undefined project_key * feat (backend-devops): Dockerfile for all services in one image * feat(sourcemap-uploader): --verbose argument use instead of --log * feat(api): log middleware * Feature - dom inspector (#28) * feat (frontend): typescript support * feat(frontend): DOM Inspector init * fix(frontend): use tailwind bg * feat(frontend dom-inspector): add element selection & deletion * fix(frontend): todo comment * di - styling wip * feature(di) - editor theme * feat(frontend): parse attributes with RE (+ability to add) * feature(di) - input width * fix(ui): di - review changes Co-authored-by: ShiKhu <alex.kaminsky.11@gmail.com> * chore(install): remove depricated init_dbs * feat(api): ee override multi-tenant-core * fix(frontend-build): gen css types before build * fix(ui) - checking for the license (#30) Co-authored-by: Rajesh Rajendran <rjshrjndrn@gmail.com> Co-authored-by: Mehdi Osman <estradino@users.noreply.github.com> Co-authored-by: ShiKhu <alex.kaminsky.11@gmail.com> Co-authored-by: KRAIEM Taha Yassine <tahayk2@gmail.com> Co-authored-by: Rajesh Rajendran <rjshrjndrn@users.noreply.github.com> Co-authored-by: ourvakan <hi-psi@yandex.com> Co-authored-by: tahayk2@gmail.com <enissay4ever4github>
296 lines
8.8 KiB
JavaScript
296 lines
8.8 KiB
JavaScript
import { List, Map } from 'immutable';
|
|
import Session from 'Types/session';
|
|
import ErrorStack from 'Types/session/errorStack';
|
|
import Watchdog, { getSessionWatchdogTypes } from 'Types/watchdog';
|
|
import { clean as cleanParams } from 'App/api_client';
|
|
import withRequestState, { RequestTypes } from './requestStateCreator';
|
|
import { getRE } from 'App/utils';
|
|
|
|
|
|
const INIT = 'sessions/INIT';
|
|
|
|
const FETCH_LIST = new RequestTypes('sessions/FETCH_LIST');
|
|
const FETCH = new RequestTypes('sessions/FETCH');
|
|
const FETCH_FAVORITE_LIST = new RequestTypes('sessions/FETCH_FAVORITE_LIST');
|
|
const TOGGLE_FAVORITE = new RequestTypes('sessions/TOGGLE_FAVORITE');
|
|
const FETCH_ERROR_STACK = new RequestTypes('sessions/FETCH_ERROR_STACK');
|
|
const SORT = 'sessions/SORT';
|
|
const REDEFINE_TARGET = 'sessions/REDEFINE_TARGET';
|
|
const SET_TIMEZONE = 'sessions/SET_TIMEZONE';
|
|
const SET_EVENT_QUERY = 'sessions/SET_EVENT_QUERY';
|
|
const SET_AUTOPLAY_VALUES = 'sessions/SET_AUTOPLAY_VALUES';
|
|
|
|
const SET_ACTIVE_TAB = 'sessions/SET_ACTIVE_TAB';
|
|
|
|
const initialState = Map({
|
|
list: List(),
|
|
sessionIds: [],
|
|
current: Session(),
|
|
total: 0,
|
|
keyMap: Map(),
|
|
wdTypeCount: Map(),
|
|
favoriteList: List(),
|
|
activeTab: Watchdog({name: 'All', type: 'all' }),
|
|
timezone: 'local',
|
|
errorStack: List(),
|
|
eventsIndex: [],
|
|
sourcemapUploaded: true,
|
|
filteredEvents: null
|
|
});
|
|
|
|
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)
|
|
case FETCH_LIST.SUCCESS:
|
|
const { sessions, total } = action.data;
|
|
const list = List(sessions).map(Session);
|
|
|
|
const { params } = action;
|
|
const eventProperties = {
|
|
eventCount: 0,
|
|
eventTypes: [],
|
|
dateFilter: params.rangeValue,
|
|
filterKeys: Object.keys(params)
|
|
.filter(key => ![ 'custom', 'startDate', 'endDate', 'strict', 'key', 'events', 'rangeValue' ].includes(key)),
|
|
returnedCount: list.size,
|
|
totalSearchCount: total,
|
|
};
|
|
if (Array.isArray(params.events)) {
|
|
eventProperties.eventCount = params.events.length;
|
|
params.events.forEach(({ type }) => {
|
|
if (!eventProperties.eventTypes.includes(type)) {
|
|
eventProperties.eventTypes.push(type);
|
|
}
|
|
})
|
|
}
|
|
|
|
const keyMap = {}
|
|
list.forEach(s => {
|
|
s.issueTypes.forEach(k => {
|
|
if(keyMap[k])
|
|
keyMap[k] += 1
|
|
else
|
|
keyMap[k] = 1;
|
|
})
|
|
})
|
|
|
|
const wdTypeCount = {}
|
|
try{
|
|
list.forEach(s => {
|
|
getSessionWatchdogTypes(s).forEach(wdtp => {
|
|
wdTypeCount[wdtp] = wdTypeCount[wdtp] ? wdTypeCount[wdtp] + 1 : 1;
|
|
})
|
|
})
|
|
} catch(e) {
|
|
|
|
}
|
|
|
|
return state
|
|
.set('list', list)
|
|
.set('sessionIds', list.map(({ sessionId }) => sessionId ).toJS())
|
|
.set('total', total)
|
|
.set('keyMap', keyMap)
|
|
.set('wdTypeCount', wdTypeCount);
|
|
|
|
case SET_AUTOPLAY_VALUES: {
|
|
const sessionIds = state.get('sessionIds')
|
|
const currentSessionId = state.get('current').sessionId
|
|
const currentIndex = sessionIds.indexOf(currentSessionId)
|
|
return state
|
|
.set('previousId', sessionIds[currentIndex - 1])
|
|
.set('nextId', sessionIds[currentIndex + 1]);
|
|
}
|
|
case SET_EVENT_QUERY: {
|
|
const events = state.get('current').events;
|
|
const query = action.filter.query;
|
|
// const filter = action.filter.filter;
|
|
const searchRe = getRE(query, 'i');
|
|
let filteredEvents = query ? events.filter(e => searchRe.test(e.url) || searchRe.test(e.value) || searchRe.test(e.label)) : null;
|
|
|
|
// if (filter) {
|
|
// filteredEvents = filteredEvents ? filteredEvents.filter(e => e.type === filter) : events.filter(e => e.type === filter);
|
|
// }
|
|
return state.set('filteredEvents', filteredEvents)
|
|
}
|
|
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) || Session();
|
|
const session = Session(action.data);
|
|
|
|
const matching = [];
|
|
|
|
events.forEach(({ key, operator, value }) => {
|
|
session.events.forEach((e, index) => {
|
|
if (key === e.type) {
|
|
const val = (e.type === 'LOCATION' ? e.url : e.value);
|
|
if (operator === 'is' && value === val) {
|
|
matching.push(index);
|
|
}
|
|
if (operator === 'contains' && val.includes(value)) {
|
|
matching.push(index);
|
|
}
|
|
}
|
|
})
|
|
})
|
|
return state.set('current', current.merge(session)).set('eventsIndex', matching);
|
|
}
|
|
case FETCH_FAVORITE_LIST.SUCCESS:
|
|
return state
|
|
.set('favoriteList', List(action.data).map(Session));
|
|
case TOGGLE_FAVORITE.SUCCESS: {
|
|
const id = action.session.sessionId;
|
|
const wasInFavorite = state
|
|
.get('favoriteList').findIndex(({ sessionId }) => sessionId === id) > -1;
|
|
return state
|
|
.update('list', list => list
|
|
.map(session => (session.sessionId === id
|
|
? session.set('favorite', !wasInFavorite)
|
|
: session)))
|
|
.update('favoriteList', list => (wasInFavorite
|
|
? list.filter(({ sessionId }) => sessionId !== id)
|
|
: list.push(action.session.set('favorite', true))))
|
|
.update('current', session => (session.sessionId === id
|
|
? session.set('favorite', !wasInFavorite)
|
|
: session));
|
|
}
|
|
case SORT: {
|
|
const comparator = (s1, s2) => {
|
|
let diff = s1[ action.sortKey ] - s2[ action.sortKey ];
|
|
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));
|
|
}
|
|
case REDEFINE_TARGET: {
|
|
// TODO: update for list
|
|
const {
|
|
label,
|
|
path,
|
|
} = action.target;
|
|
return state.updateIn([ 'current', 'events' ], list =>
|
|
list.map(event => (event.target && event.target.path === path
|
|
? event.setIn([ 'target', 'label' ], label)
|
|
: event)));
|
|
}
|
|
case SET_ACTIVE_TAB:
|
|
const allList = action.tab.type === 'all' ?
|
|
state.get('list') :
|
|
state.get('list').filter(s => s.issueTypes.includes(action.tab.type))
|
|
|
|
return state
|
|
.set('activeTab', action.tab)
|
|
.set('sessionIds', allList.map(({ sessionId }) => sessionId ).toJS())
|
|
case SET_TIMEZONE:
|
|
return state.set('timezone', action.timezone)
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
export default withRequestState({
|
|
_: [ FETCH, FETCH_LIST ],
|
|
fetchFavoriteListRequest: FETCH_FAVORITE_LIST,
|
|
toggleFavoriteRequest: TOGGLE_FAVORITE,
|
|
fetchErrorStackList: FETCH_ERROR_STACK,
|
|
}, reducer);
|
|
|
|
function init(session) {
|
|
return {
|
|
type: INIT,
|
|
session,
|
|
}
|
|
}
|
|
|
|
export function fetchList(params = {}, clear = false) {
|
|
return {
|
|
types: FETCH_LIST.toArray(),
|
|
call: client => client.post('/sessions/search2', params),
|
|
clear,
|
|
params: cleanParams(params),
|
|
};
|
|
}
|
|
|
|
export function fetchErrorStackList(sessionId, errorId) {
|
|
return {
|
|
types: FETCH_ERROR_STACK.toArray(),
|
|
call: client => client.get(`/sessions2/${ sessionId }/errors/${ errorId }/sourcemaps`)
|
|
};
|
|
}
|
|
|
|
export const fetch = (sessionId) => (dispatch, getState) => {
|
|
dispatch({
|
|
types: FETCH.toArray(),
|
|
call: client => client.get(`/sessions2/${ sessionId }`),
|
|
filter: getState().getIn([ 'filters', 'appliedFilter' ])
|
|
});
|
|
}
|
|
|
|
export function toggleFavorite(session) {
|
|
return {
|
|
types: TOGGLE_FAVORITE.toArray(),
|
|
call: client => client.get(`/sessions2/${ session.sessionId }/favorite`),
|
|
session,
|
|
};
|
|
}
|
|
|
|
export function fetchFavoriteList() {
|
|
return {
|
|
types: FETCH_FAVORITE_LIST.toArray(),
|
|
call: client => client.get('/sessions2/favorite'),
|
|
};
|
|
}
|
|
|
|
export function sort(sortKey, sign = 1, listName = 'list') {
|
|
return {
|
|
type: SORT,
|
|
sortKey,
|
|
sign,
|
|
listName,
|
|
};
|
|
}
|
|
|
|
export function redefineTarget(target) {
|
|
return {
|
|
type: REDEFINE_TARGET,
|
|
target,
|
|
};
|
|
}
|
|
|
|
export const setAutoplayValues = (sessionId) => {
|
|
return {
|
|
type: SET_AUTOPLAY_VALUES,
|
|
sessionId,
|
|
};
|
|
}
|
|
|
|
export const setActiveTab = (tab) => ({
|
|
type: SET_ACTIVE_TAB,
|
|
tab
|
|
})
|
|
|
|
export function setTimezone(timezone) {
|
|
return {
|
|
type: SET_TIMEZONE,
|
|
timezone,
|
|
};
|
|
}
|
|
|
|
export function setEventFilter(filter) {
|
|
return {
|
|
type: SET_EVENT_QUERY,
|
|
filter
|
|
}
|
|
}
|
|
|