feat(ui) - sessions - widget
This commit is contained in:
parent
f1d94c5378
commit
82ad650f0c
15 changed files with 196 additions and 6 deletions
|
|
@ -1,8 +1,15 @@
|
|||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import ErrorListItem from '../ErrorListItem';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
|
||||
function ErrorsList(props) {
|
||||
|
||||
const { errorStore, metricStore } = useStore();
|
||||
const metric = useObserver(() => metricStore.instance);
|
||||
|
||||
useEffect(() => {
|
||||
errorStore.fetchErrors();
|
||||
}, []);
|
||||
return (
|
||||
<div>
|
||||
Errors List
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
import React from 'react';
|
||||
import SessionListItem from '../SessionListItem';
|
||||
|
||||
function SessionList(props) {
|
||||
return (
|
||||
<div>
|
||||
Session list
|
||||
<SessionListItem session={{}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionList;
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SessionList';
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
session: any;
|
||||
}
|
||||
function SessionListItem(props: Props) {
|
||||
return (
|
||||
<div>
|
||||
Session list item
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionListItem;
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SessionListItem';
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
import SessionList from '../SessionList';
|
||||
|
||||
function SessionWidget(props) {
|
||||
return (
|
||||
<div>
|
||||
<SessionList />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionWidget;
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SessionWidget';
|
||||
|
|
@ -13,6 +13,7 @@ import { getStartAndEndTimestampsByDensity } from 'Types/dashboard/helper';
|
|||
import { debounce } from 'App/utils';
|
||||
import FunnelWidget from 'App/components/Funnels/FunnelWidget';
|
||||
import ErrorsWidget from '../Errors/ErrorsWidget';
|
||||
import SessionWidget from '../Sessions/SessionWidget';
|
||||
interface Props {
|
||||
metric: any;
|
||||
isWidget?: boolean
|
||||
|
|
@ -84,6 +85,10 @@ function WidgetChart(props: Props) {
|
|||
const renderChart = () => {
|
||||
const { metricType, viewType } = metric;
|
||||
|
||||
if (metricType === 'sessions') {
|
||||
return <SessionWidget metric={metric} />
|
||||
}
|
||||
|
||||
if (metricType === 'errors') {
|
||||
return <ErrorsWidget metric={metric} />
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ function WidgetView(props: Props) {
|
|||
const { metricStore } = useStore();
|
||||
const widget = useObserver(() => metricStore.instance);
|
||||
const loading = useObserver(() => metricStore.isLoading);
|
||||
const isFunnel = widget.metricType === 'funnel';
|
||||
const [expanded, setExpanded] = useState(!metricId || metricId === 'create');
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -73,8 +72,8 @@ function WidgetView(props: Props) {
|
|||
</div>
|
||||
|
||||
<WidgetPreview className="mt-8" />
|
||||
{ !isFunnel && <WidgetSessions className="mt-8" /> }
|
||||
{ isFunnel && <FunnelIssues /> }
|
||||
{ (widget.metricType === 'table' || widget.metricType === 'timeseries') && <WidgetSessions className="mt-8" /> }
|
||||
{ widget.metricType === 'funnel' && <FunnelIssues /> }
|
||||
</div>
|
||||
</Loader>
|
||||
));
|
||||
|
|
|
|||
55
frontend/app/mstore/errorStore.ts
Normal file
55
frontend/app/mstore/errorStore.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import { makeAutoObservable, runInAction, observable, action, reaction } from "mobx"
|
||||
import { errorService } from "App/services"
|
||||
import Error from "./types/error"
|
||||
|
||||
export default class ErrorStore {
|
||||
isLoading: boolean = false
|
||||
isSaving: boolean = false
|
||||
|
||||
errors: any[] = []
|
||||
instance: Error | null = null
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
updateKey(key: string, value: any) {
|
||||
this[key] = value
|
||||
}
|
||||
|
||||
fetchErrors(): Promise<any> {
|
||||
this.isLoading = true
|
||||
return new Promise((resolve, reject) => {
|
||||
errorService.all()
|
||||
.then(response => {
|
||||
const errors = response.map(e => new Error().fromJSON(e));
|
||||
this.errors = errors
|
||||
resolve(errors)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.isLoading = false
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fetchError(errorId: string): Promise<any> {
|
||||
this.isLoading = true
|
||||
return new Promise((resolve, reject) => {
|
||||
errorService.one(errorId)
|
||||
.then(response => {
|
||||
const error = new Error().fromJSON(response);
|
||||
this.instance = error
|
||||
resolve(error)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.isLoading = false
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -5,9 +5,18 @@ import UserStore from './userStore';
|
|||
import RoleStore from './roleStore';
|
||||
import APIClient from 'App/api_client';
|
||||
import FunnelStore from './funnelStore';
|
||||
import { dashboardService, metricService, funnelService, sessionService, userService, auditService } from 'App/services';
|
||||
import {
|
||||
dashboardService,
|
||||
metricService,
|
||||
funnelService,
|
||||
sessionService,
|
||||
userService,
|
||||
auditService,
|
||||
errorService,
|
||||
} from 'App/services';
|
||||
import SettingsStore from './settingsStore';
|
||||
import AuditStore from './auditStore';
|
||||
import ErrorStore from './errorStore';
|
||||
|
||||
export class RootStore {
|
||||
dashboardStore: IDashboardSotre;
|
||||
|
|
@ -17,6 +26,7 @@ export class RootStore {
|
|||
userStore: UserStore;
|
||||
roleStore: RoleStore;
|
||||
auditStore: AuditStore;
|
||||
errorStore: ErrorStore;
|
||||
|
||||
constructor() {
|
||||
this.dashboardStore = new DashboardStore();
|
||||
|
|
@ -26,6 +36,7 @@ export class RootStore {
|
|||
this.userStore = new UserStore();
|
||||
this.roleStore = new RoleStore();
|
||||
this.auditStore = new AuditStore();
|
||||
this.errorStore = new ErrorStore();
|
||||
}
|
||||
|
||||
initClient() {
|
||||
|
|
@ -36,6 +47,7 @@ export class RootStore {
|
|||
sessionService.initClient(client)
|
||||
userService.initClient(client)
|
||||
auditService.initClient(client)
|
||||
errorService.initClient(client)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
42
frontend/app/mstore/types/error.ts
Normal file
42
frontend/app/mstore/types/error.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
export default class Error {
|
||||
sessionId: string = ''
|
||||
messageId: string = ''
|
||||
timestamp: string = ''
|
||||
errorId: string = ''
|
||||
projectId: string = ''
|
||||
source: string = ''
|
||||
name: string = ''
|
||||
message: string = ''
|
||||
time: string = ''
|
||||
function: string = '?'
|
||||
stack0InfoString: string = ''
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
fromJSON(json: any) {
|
||||
this.sessionId = json.sessionId
|
||||
this.messageId = json.messageId
|
||||
this.timestamp = json.timestamp
|
||||
this.errorId = json.errorId
|
||||
this.projectId = json.projectId
|
||||
this.source = json.source
|
||||
this.name = json.name
|
||||
this.message = json.message
|
||||
this.time = json.time
|
||||
this.function = json.function
|
||||
this.stack0InfoString = getStck0InfoString(json.stack || [])
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
function getStck0InfoString(stack) {
|
||||
const stack0 = stack[0];
|
||||
if (!stack0) return "";
|
||||
let s = stack0.function || "";
|
||||
if (stack0.url) {
|
||||
s += ` (${stack0.url})`;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
12
frontend/app/services/BaseService.ts
Normal file
12
frontend/app/services/BaseService.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import APIClient from 'App/api_client';
|
||||
export default class BaseService {
|
||||
client: APIClient;
|
||||
|
||||
constructor(client?: APIClient) {
|
||||
this.client = client ? client : new APIClient();
|
||||
}
|
||||
|
||||
initClient(client?: APIClient) {
|
||||
this.client = client || new APIClient();
|
||||
}
|
||||
}
|
||||
14
frontend/app/services/ErrorService.ts
Normal file
14
frontend/app/services/ErrorService.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import BaseService from './BaseService';
|
||||
|
||||
export default class ErrorService extends BaseService {
|
||||
all(params: any = {}): Promise<any[]> {
|
||||
return this.client.post('/errors/search', params)
|
||||
.then(response => response.json())
|
||||
.then(response => response.data || []);
|
||||
}
|
||||
|
||||
one(id: string): Promise<any> {
|
||||
return this.client.get(`/errors/${id}`)
|
||||
.then(response => response.json())
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import FunnelService, { IFunnelService } from "./FunnelService";
|
|||
import SessionSerivce from "./SessionService";
|
||||
import UserService from "./UserService";
|
||||
import AuditService from './AuditService';
|
||||
import ErrorService from "./ErrorService";
|
||||
|
||||
export const dashboardService: IDashboardService = new DashboardService();
|
||||
export const metricService: IMetricService = new MetricService();
|
||||
|
|
@ -11,3 +12,4 @@ export const sessionService: SessionSerivce = new SessionSerivce();
|
|||
export const userService: UserService = new UserService();
|
||||
export const funnelService: IFunnelService = new FunnelService();
|
||||
export const auditService: AuditService = new AuditService();
|
||||
export const errorService: ErrorService = new ErrorService();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue