feat(ui) - dashboards wip
This commit is contained in:
parent
b8bd169839
commit
38b536aae1
17 changed files with 555 additions and 6 deletions
|
|
@ -14,7 +14,8 @@ import SessionPure from 'Components/Session/Session';
|
|||
import LiveSessionPure from 'Components/Session/LiveSession';
|
||||
import AssistPure from 'Components/Assist';
|
||||
import BugFinderPure from 'Components/BugFinder/BugFinder';
|
||||
import DashboardPure from 'Components/Dashboard/Dashboard';
|
||||
import DashboardPure from 'Components/Dashboard/NewDashboard';
|
||||
import WidgetViewPure from 'Components/Dashboard/WidgetView';
|
||||
import ErrorsPure from 'Components/Errors/Errors';
|
||||
import Header from 'Components/Header/Header';
|
||||
// import ResultsModal from 'Shared/Results/ResultsModal';
|
||||
|
|
@ -35,6 +36,7 @@ import { setSessionPath } from 'Duck/sessions';
|
|||
|
||||
const BugFinder = withSiteIdUpdater(BugFinderPure);
|
||||
const Dashboard = withSiteIdUpdater(DashboardPure);
|
||||
const WidgetView = withSiteIdUpdater(WidgetViewPure);
|
||||
const Session = withSiteIdUpdater(SessionPure);
|
||||
const LiveSession = withSiteIdUpdater(LiveSessionPure);
|
||||
const Assist = withSiteIdUpdater(AssistPure);
|
||||
|
|
@ -46,7 +48,8 @@ const FunnelIssue = withSiteIdUpdater(FunnelIssueDetails);
|
|||
const withSiteId = routes.withSiteId;
|
||||
const withObTab = routes.withObTab;
|
||||
|
||||
const DASHBOARD_PATH = routes.dashboard();
|
||||
const DASHBOARD_PATH = routes.dashboardSelected();
|
||||
const WIDGET_PATAH = routes.dashboardMetric();
|
||||
const SESSIONS_PATH = routes.sessions();
|
||||
const ASSIST_PATH = routes.assist();
|
||||
const ERRORS_PATH = routes.errors();
|
||||
|
|
@ -180,6 +183,7 @@ class Router extends React.Component {
|
|||
<Redirect to={ routes.client(routes.CLIENT_TABS.SITES) } />
|
||||
}
|
||||
<Route exact strict path={ withSiteId(DASHBOARD_PATH, siteIdList) } component={ Dashboard } />
|
||||
<Route exact strict path={ withSiteId(WIDGET_PATAH, siteIdList) } component={ Dashboard } />
|
||||
<Route exact strict path={ withSiteId(ASSIST_PATH, siteIdList) } component={ Assist } />
|
||||
<Route exact strict path={ withSiteId(ERRORS_PATH, siteIdList) } component={ Errors } />
|
||||
<Route exact strict path={ withSiteId(ERROR_PATH, siteIdList) } component={ Errors } />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import store from 'App/store';
|
||||
|
||||
import { queried } from './routes';
|
||||
|
||||
const siteIdRequiredPaths = [
|
||||
|
|
|
|||
45
frontend/app/components/Dashboard/NewDashboard.tsx
Normal file
45
frontend/app/components/Dashboard/NewDashboard.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { Switch, Route, Redirect } from 'react-router';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { withDashboardStore } from './store/store';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import DashboardView from './components/DashboardView';
|
||||
import { dashboardSelected, dashboardMetric, withSiteId } from 'App/routes';
|
||||
|
||||
function NewDashboard(props) {
|
||||
const { store, match: { params: { siteId, dashboardId, metricId } } } = props;
|
||||
const dashboard = store.selectedDashboard;
|
||||
|
||||
useEffect(() => {
|
||||
store.setSiteId(siteId);
|
||||
if (dashboardId) {
|
||||
store.selectDashboardById(dashboardId);
|
||||
} else {
|
||||
store.selectDefaultDashboard();
|
||||
}
|
||||
}, [dashboardId]);
|
||||
|
||||
return (
|
||||
<div className="page-margin container-90">
|
||||
<div className="side-menu">
|
||||
MENU
|
||||
</div>
|
||||
<div className="side-menu-margined">
|
||||
<Switch>
|
||||
<Route exact path={withSiteId(dashboardSelected(dashboardId), siteId)}>
|
||||
<DashboardView dashboard={dashboard} />
|
||||
</Route>
|
||||
<Route exact path={withSiteId(dashboardMetric(dashboardId, metricId), siteId)}>
|
||||
<h1>Metric</h1>
|
||||
</Route>
|
||||
<Redirect to={withSiteId(dashboardSelected(dashboardId), siteId )} />
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default withPageTitle('New Dashboard')(
|
||||
withRouter(withDashboardStore(observer(NewDashboard)))
|
||||
);
|
||||
11
frontend/app/components/Dashboard/WidgetView/WidgetView.tsx
Normal file
11
frontend/app/components/Dashboard/WidgetView/WidgetView.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
|
||||
function WidgetView(props) {
|
||||
return (
|
||||
<div>
|
||||
Widget view
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default WidgetView;
|
||||
1
frontend/app/components/Dashboard/WidgetView/index.ts
Normal file
1
frontend/app/components/Dashboard/WidgetView/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './WidgetView'
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useDashboardStore } from '../store/store';
|
||||
import cn from 'classnames';
|
||||
import { Link } from 'UI';
|
||||
import { dashboardMetric, withSiteId } from 'App/routes';
|
||||
|
||||
function WidgetWrapper(props) {
|
||||
const { widget } = props;
|
||||
const store: any = useDashboardStore();
|
||||
const dashboard = store.selectedDashboard;
|
||||
const siteId = store.siteId;
|
||||
|
||||
return (
|
||||
<div className={cn("border rounded", 'col-span-' + widget.colSpan)} style={{ userSelect: 'none'}}>
|
||||
<Link to={withSiteId(dashboardMetric(12, widget.widgetId), siteId)}>
|
||||
<div className="p-3 cursor-pointer bg-white border-b flex items-center justify-between">
|
||||
{widget.name} - {widget.position}
|
||||
<div>
|
||||
<button className="btn btn-sm btn-outline-primary" onClick={() => dashboard.removeWidget(widget.widgetId)}>
|
||||
remove
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white h-40">
|
||||
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default observer(WidgetWrapper);
|
||||
1
frontend/app/components/Dashboard/WidgetWrapper/index.ts
Normal file
1
frontend/app/components/Dashboard/WidgetWrapper/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './WidgetWrapper';
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import React from 'react';
|
||||
import WidgetWrapper from '../../WidgetWrapper';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { withDashboardStore } from '../../store/store';
|
||||
|
||||
function DashboardView(props) {
|
||||
const { store } = props;
|
||||
const dashboard = store.selectedDashboard
|
||||
const list = dashboard?.widgets;
|
||||
return dashboard ? (
|
||||
<div>
|
||||
test {dashboard.dashboardId}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{list && list.map(item => <WidgetWrapper widget={item} key={item.widgetId} />)}
|
||||
</div>
|
||||
</div>
|
||||
) : <h1>Loading...</h1>;
|
||||
}
|
||||
|
||||
export default withDashboardStore(observer(DashboardView));
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './DashboardView'
|
||||
115
frontend/app/components/Dashboard/store/dashboard.ts
Normal file
115
frontend/app/components/Dashboard/store/dashboard.ts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import { makeAutoObservable, makeObservable, observable, action, runInAction, computed, reaction } from "mobx"
|
||||
import Widget from "./widget"
|
||||
// import APIClient from 'App/api_client';
|
||||
|
||||
export default class Dashboard {
|
||||
dashboardId: any = undefined
|
||||
name: string = "New Dashboard"
|
||||
isPriavte: boolean = false
|
||||
widgets: Widget[] = []
|
||||
isValid: boolean = false
|
||||
isPinned: boolean = false
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
name: observable,
|
||||
isPriavte: observable,
|
||||
widgets: observable,
|
||||
isValid: observable,
|
||||
|
||||
toJson: action,
|
||||
fromJson: action,
|
||||
addWidget: action,
|
||||
removeWidget: action,
|
||||
updateWidget: action,
|
||||
getWidget: action,
|
||||
getWidgetIndex: action,
|
||||
getWidgetByIndex: action,
|
||||
getWidgetCount: action,
|
||||
getWidgetIndexByWidgetId: action,
|
||||
validate: action,
|
||||
sortWidgets: action,
|
||||
swapWidgetPosition: action,
|
||||
})
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
dashboardId: this.dashboardId,
|
||||
name: this.name,
|
||||
isPrivate: this.isPriavte,
|
||||
widgets: this.widgets.map(w => w.toJson())
|
||||
}
|
||||
}
|
||||
|
||||
fromJson(json: any) {
|
||||
runInAction(() => {
|
||||
this.dashboardId = json.dashboardId
|
||||
this.name = json.name
|
||||
this.isPriavte = json.isPrivate
|
||||
this.widgets = json.widgets.map(w => new Widget().fromJson(w))
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
validate() {
|
||||
this.isValid = this.name.length > 0
|
||||
}
|
||||
|
||||
addWidget(widget: Widget) {
|
||||
this.widgets.push(widget)
|
||||
}
|
||||
|
||||
removeWidget(widgetId: string) {
|
||||
this.widgets = this.widgets.filter(w => w.widgetId !== widgetId)
|
||||
}
|
||||
|
||||
updateWidget(widget: Widget) {
|
||||
const index = this.widgets.findIndex(w => w.widgetId === widget.widgetId)
|
||||
if (index >= 0) {
|
||||
this.widgets[index] = widget
|
||||
}
|
||||
}
|
||||
|
||||
getWidget(widgetId: string) {
|
||||
return this.widgets.find(w => w.widgetId === widgetId)
|
||||
}
|
||||
|
||||
getWidgetIndex(widgetId: string) {
|
||||
return this.widgets.findIndex(w => w.widgetId === widgetId)
|
||||
}
|
||||
|
||||
getWidgetByIndex(index: number) {
|
||||
return this.widgets[index]
|
||||
}
|
||||
|
||||
getWidgetCount() {
|
||||
return this.widgets.length
|
||||
}
|
||||
|
||||
getWidgetIndexByWidgetId(widgetId: string) {
|
||||
return this.widgets.findIndex(w => w.widgetId === widgetId)
|
||||
}
|
||||
|
||||
swapWidgetPosition(positionA, positionB) {
|
||||
const widgetA = this.widgets[positionA]
|
||||
const widgetB = this.widgets[positionB]
|
||||
this.widgets[positionA] = widgetB
|
||||
this.widgets[positionB] = widgetA
|
||||
|
||||
widgetA.position = positionB
|
||||
widgetB.position = positionA
|
||||
}
|
||||
|
||||
sortWidgets() {
|
||||
this.widgets = this.widgets.sort((a, b) => {
|
||||
if (a.position > b.position) {
|
||||
return 1
|
||||
} else if (a.position < b.position) {
|
||||
return -1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
233
frontend/app/components/Dashboard/store/dashboardStore.ts
Normal file
233
frontend/app/components/Dashboard/store/dashboardStore.ts
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
import { makeAutoObservable, runInAction, observable, action, reaction } from "mobx"
|
||||
import Dashboard from "./dashboard"
|
||||
import APIClient from 'App/api_client';
|
||||
import Widget from "./widget";
|
||||
|
||||
export default class DashboardStore {
|
||||
dashboards: Dashboard[] = []
|
||||
selectedDashboard: Dashboard | null = null
|
||||
isLoading: boolean = false
|
||||
siteId: any = null
|
||||
|
||||
private client = new APIClient()
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
dashboards: observable,
|
||||
selectedDashboard: observable,
|
||||
isLoading: observable,
|
||||
|
||||
addDashboard: action,
|
||||
removeDashboard: action,
|
||||
updateDashboard: action,
|
||||
getDashboard: action,
|
||||
getDashboardIndex: action,
|
||||
getDashboardByIndex: action,
|
||||
getDashboardCount: action,
|
||||
getDashboardIndexByDashboardId: action,
|
||||
selectDashboardById: action,
|
||||
toJson: action,
|
||||
fromJson: action,
|
||||
setSiteId: action,
|
||||
})
|
||||
|
||||
|
||||
// TODO remove this sample data
|
||||
this.dashboards = sampleDashboards
|
||||
this.selectedDashboard = sampleDashboards[0]
|
||||
|
||||
// setInterval(() => {
|
||||
// this.selectedDashboard?.addWidget(getRandomWidget())
|
||||
// }, 3000)
|
||||
|
||||
// setInterval(() => {
|
||||
// this.selectedDashboard?.widgets[4].update({ position: 2 })
|
||||
// this.selectedDashboard?.swapWidgetPosition(2, 0)
|
||||
// }, 3000)
|
||||
}
|
||||
|
||||
fetchList() {
|
||||
this.isLoading = true
|
||||
|
||||
this.client.get('/dashboards')
|
||||
.then(response => {
|
||||
runInAction(() => {
|
||||
this.dashboards = response.data.map(d => new Dashboard().fromJson(d))
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fetch(dashboardId: string) {
|
||||
this.isLoading = true
|
||||
this.client.get(`/dashboards/${dashboardId}`)
|
||||
.then(response => {
|
||||
runInAction(() => {
|
||||
this.selectedDashboard = new Dashboard().fromJson(response.data)
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
save(dashboard: Dashboard) {
|
||||
dashboard.validate()
|
||||
if (dashboard.isValid) {
|
||||
this.isLoading = true
|
||||
if (dashboard.dashboardId) {
|
||||
this.client.put(`/dashboards/${dashboard.dashboardId}`, dashboard.toJson())
|
||||
.then(response => {
|
||||
runInAction(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
)
|
||||
} else {
|
||||
this.client.post('/dashboards', dashboard.toJson())
|
||||
.then(response => {
|
||||
runInAction(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
alert("Invalid dashboard") // TODO show validation errors
|
||||
}
|
||||
}
|
||||
|
||||
saveDashboardWidget(dashboard: Dashboard, widget: Widget) {
|
||||
widget.validate()
|
||||
if (widget.isValid) {
|
||||
this.isLoading = true
|
||||
if (widget.widgetId) {
|
||||
this.client.put(`/dashboards/${dashboard.dashboardId}/widgets/${widget.widgetId}`, widget.toJson())
|
||||
.then(response => {
|
||||
runInAction(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
)
|
||||
} else {
|
||||
this.client.post(`/dashboards/${dashboard.dashboardId}/widgets`, widget.toJson())
|
||||
.then(response => {
|
||||
runInAction(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete(dashboard: Dashboard) {
|
||||
this.isLoading = true
|
||||
this.client.delete(`/dashboards/${dashboard.dashboardId}`)
|
||||
.then(response => {
|
||||
runInAction(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
dashboards: this.dashboards.map(d => d.toJson())
|
||||
}
|
||||
}
|
||||
|
||||
fromJson(json: any) {
|
||||
runInAction(() => {
|
||||
this.dashboards = json.dashboards.map(d => new Dashboard().fromJson(d))
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
initDashboard(dashboard: Dashboard | null) {
|
||||
this.selectedDashboard = dashboard || new Dashboard()
|
||||
}
|
||||
|
||||
addDashboard(dashboard: Dashboard) {
|
||||
this.dashboards.push(dashboard)
|
||||
}
|
||||
|
||||
removeDashboard(dashboard: Dashboard) {
|
||||
this.dashboards = this.dashboards.filter(d => d !== dashboard)
|
||||
}
|
||||
|
||||
getDashboard(dashboardId: string) {
|
||||
return this.dashboards.find(d => d.dashboardId === dashboardId)
|
||||
}
|
||||
|
||||
getDashboardIndex(dashboardId: string) {
|
||||
return this.dashboards.findIndex(d => d.dashboardId === dashboardId)
|
||||
}
|
||||
|
||||
getDashboardByIndex(index: number) {
|
||||
return this.dashboards[index]
|
||||
}
|
||||
|
||||
getDashboardCount() {
|
||||
return this.dashboards.length
|
||||
}
|
||||
|
||||
getDashboardIndexByDashboardId(dashboardId: string) {
|
||||
return this.dashboards.findIndex(d => d.dashboardId === dashboardId)
|
||||
}
|
||||
|
||||
updateDashboard(dashboard: Dashboard) {
|
||||
const index = this.dashboards.findIndex(d => d.dashboardId === dashboard.dashboardId)
|
||||
if (index >= 0) {
|
||||
this.dashboards[index] = dashboard
|
||||
}
|
||||
}
|
||||
|
||||
selectDashboardById = (dashboardId: any) => {
|
||||
this.selectedDashboard = this.dashboards.find(d => d.dashboardId == dashboardId) || null;;
|
||||
}
|
||||
|
||||
setSiteId = (siteId: any) => {
|
||||
this.siteId = siteId
|
||||
}
|
||||
|
||||
selectDefaultDashboard = () => {
|
||||
const pinnedDashboard = this.dashboards.find(d => d.isPinned)
|
||||
if (pinnedDashboard) {
|
||||
this.selectedDashboard = pinnedDashboard
|
||||
} else {
|
||||
this.selectedDashboard = this.dashboards[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getRandomWidget() {
|
||||
const widget = new Widget();
|
||||
widget.widgetId = Math.floor(Math.random() * 100);
|
||||
widget.name = "Widget " + Math.floor(Math.random() * 100);
|
||||
widget.type = "random";
|
||||
widget.colSpan = Math.floor(Math.random() * 2) + 1;
|
||||
return widget;
|
||||
}
|
||||
|
||||
function getRandomDashboard(id: any = null) {
|
||||
const dashboard = new Dashboard();
|
||||
dashboard.name = "Random Dashboard";
|
||||
dashboard.dashboardId = id ? id : "random-dashboard-" + Math.floor(Math.random() * 10);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const widget = getRandomWidget();
|
||||
widget.position = i;
|
||||
dashboard.addWidget(widget);
|
||||
}
|
||||
return dashboard;
|
||||
}
|
||||
|
||||
const sampleDashboards = [
|
||||
getRandomDashboard(12),
|
||||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
]
|
||||
1
frontend/app/components/Dashboard/store/index.ts
Normal file
1
frontend/app/components/Dashboard/store/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './dashboardStore'
|
||||
15
frontend/app/components/Dashboard/store/store.tsx
Normal file
15
frontend/app/components/Dashboard/store/store.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import React from 'react'
|
||||
|
||||
const StoreContext = React.createContext(null)
|
||||
|
||||
export const DashboardStoreProvider = ({ children, store }) => {
|
||||
return (
|
||||
<StoreContext.Provider value={store}>{children}</StoreContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useDashboardStore = () => React.useContext(StoreContext);
|
||||
|
||||
export const withDashboardStore = (Component) => (props) => {
|
||||
return <Component {...props} store={useDashboardStore()} />;
|
||||
};
|
||||
61
frontend/app/components/Dashboard/store/widget.ts
Normal file
61
frontend/app/components/Dashboard/store/widget.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import { makeAutoObservable, runInAction, observable, action, reaction } from "mobx"
|
||||
|
||||
export default class Widget {
|
||||
widgetId: any = undefined
|
||||
name: string = ""
|
||||
type: string = ""
|
||||
position: number = 0
|
||||
data: any = {}
|
||||
isLoading: boolean = false
|
||||
isValid: boolean = false
|
||||
dashboardId: any = undefined
|
||||
colSpan: number = 2
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
widgetId: observable,
|
||||
name: observable,
|
||||
type: observable,
|
||||
position: observable,
|
||||
data: observable,
|
||||
isLoading: observable,
|
||||
isValid: observable,
|
||||
dashboardId: observable,
|
||||
colSpan: observable,
|
||||
|
||||
fromJson: action,
|
||||
toJson: action,
|
||||
validate: action,
|
||||
update: action,
|
||||
})
|
||||
}
|
||||
|
||||
fromJson(json: any) {
|
||||
runInAction(() => {
|
||||
this.widgetId = json.widgetId
|
||||
this.name = json.name
|
||||
this.type = json.type
|
||||
this.data = json.data
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
widgetId: this.widgetId,
|
||||
name: this.name,
|
||||
type: this.type,
|
||||
data: this.data
|
||||
}
|
||||
}
|
||||
|
||||
validate() {
|
||||
this.isValid = this.name.length > 0
|
||||
}
|
||||
|
||||
update(data: any) {
|
||||
runInAction(() => {
|
||||
Object.assign(this, data)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ const Header = (props) => {
|
|||
className={ styles.nav }
|
||||
activeClassName={ styles.active }
|
||||
>
|
||||
<span>{ 'Metrics' }</span>
|
||||
<span>{ 'Dashboard' }</span>
|
||||
</NavLink>
|
||||
<div className={ styles.right }>
|
||||
<Announcements />
|
||||
|
|
|
|||
|
|
@ -5,12 +5,18 @@ import { Provider } from 'react-redux';
|
|||
|
||||
import store from './store';
|
||||
import Router from './Router';
|
||||
import DashboardStore from './components/Dashboard/store';
|
||||
import { DashboardStoreProvider } from './components/Dashboard/store/store';
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const dashboardStore = new DashboardStore();
|
||||
render(
|
||||
(
|
||||
<Provider store={ store }>
|
||||
<Router />
|
||||
<DashboardStoreProvider store={ dashboardStore }>
|
||||
<Router />
|
||||
</DashboardStoreProvider>
|
||||
</Provider>
|
||||
),
|
||||
document.getElementById('app'),
|
||||
|
|
|
|||
|
|
@ -100,7 +100,9 @@ export const testBuilderNew = () => '/test-builder';
|
|||
|
||||
export const testBuilder = (testId = ':testId') => `/test-builder/${ testId }`;
|
||||
|
||||
export const dashboard = () => '/metrics';
|
||||
export const dashboard = () => '/dashboard';
|
||||
export const dashboardSelected = (id = ':dashboardId', hash) => hashed(`/dashboard/${ id }`, hash);
|
||||
export const dashboardMetric = (id = ':dashboardId', metricId = ':metricId', hash) => hashed(`/dashboard/${ id }/metric/${metricId}`, hash);
|
||||
|
||||
export const RESULTS_QUERY_KEY = 'results';
|
||||
export const METRICS_QUERY_KEY = 'metrics';
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue