feat(ui) - dashboards wip
This commit is contained in:
parent
38b536aae1
commit
391189e894
14 changed files with 114 additions and 20 deletions
|
|
@ -1,11 +1,12 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { Switch, Route, Redirect } from 'react-router';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { observer, useObserver } 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';
|
||||
import DashboardSideMenu from './components/DashboardSideMenu';
|
||||
|
||||
function NewDashboard(props) {
|
||||
const { store, match: { params: { siteId, dashboardId, metricId } } } = props;
|
||||
|
|
@ -20,10 +21,10 @@ function NewDashboard(props) {
|
|||
}
|
||||
}, [dashboardId]);
|
||||
|
||||
return (
|
||||
return useObserver(() => (
|
||||
<div className="page-margin container-90">
|
||||
<div className="side-menu">
|
||||
MENU
|
||||
<DashboardSideMenu />
|
||||
</div>
|
||||
<div className="side-menu-margined">
|
||||
<Switch>
|
||||
|
|
@ -37,9 +38,9 @@ function NewDashboard(props) {
|
|||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
export default withPageTitle('New Dashboard')(
|
||||
withRouter(withDashboardStore(observer(NewDashboard)))
|
||||
withRouter(withDashboardStore(NewDashboard))
|
||||
);
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import { useObserver } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { SideMenuitem, SideMenuHeader } from 'UI';
|
||||
import { withDashboardStore } from '../../store/store';
|
||||
|
||||
function DashboardSideMenu(props) {
|
||||
const { store } = props;
|
||||
const { selectedDashboard } = store;
|
||||
|
||||
const onItemClick = (dashboard) => {
|
||||
store.selectDashboardById(dashboard.dashboardId);
|
||||
};
|
||||
|
||||
return useObserver(() => (
|
||||
<div>
|
||||
<SideMenuHeader className="mb-4" text="Dashboards" />
|
||||
{store.dashboards.map(item => (
|
||||
<SideMenuitem
|
||||
key={ item.key }
|
||||
active={ item.active }
|
||||
title={ item.name }
|
||||
iconName={ item.icon }
|
||||
onClick={() => onItemClick(item)}
|
||||
/>
|
||||
))}
|
||||
<div className="border-t w-full my-2" />
|
||||
<div className="">
|
||||
<SideMenuitem
|
||||
id="menu-manage-alerts"
|
||||
title="Metrics"
|
||||
iconName="bar-chart-line"
|
||||
// onClick={() => setShowAlerts(true)}
|
||||
/>
|
||||
</div>
|
||||
<div className="border-t w-full my-2" />
|
||||
<div className="my-3">
|
||||
<SideMenuitem
|
||||
id="menu-manage-alerts"
|
||||
title="Alerts"
|
||||
iconName="bell-plus"
|
||||
// onClick={() => setShowAlerts(true)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
}
|
||||
|
||||
export default withDashboardStore(DashboardSideMenu);
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from './DashboardSideMenu';
|
||||
|
|
@ -2,19 +2,23 @@ import React from 'react';
|
|||
import WidgetWrapper from '../../WidgetWrapper';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { withDashboardStore } from '../../store/store';
|
||||
import { Button, PageTitle } from 'UI';
|
||||
|
||||
function DashboardView(props) {
|
||||
const { store } = props;
|
||||
const dashboard = store.selectedDashboard
|
||||
const list = dashboard?.widgets;
|
||||
return dashboard ? (
|
||||
return (
|
||||
<div>
|
||||
test {dashboard.dashboardId}
|
||||
<div className="flex items-center mb-4">
|
||||
<PageTitle title={dashboard.name} className="mr-3" />
|
||||
<Button primary size="small">Add Metric</Button>
|
||||
</div>
|
||||
<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));
|
||||
|
|
@ -5,7 +5,7 @@ import Widget from "./widget";
|
|||
|
||||
export default class DashboardStore {
|
||||
dashboards: Dashboard[] = []
|
||||
selectedDashboard: Dashboard | null = null
|
||||
selectedDashboard: Dashboard | null = new Dashboard()
|
||||
isLoading: boolean = false
|
||||
siteId: any = null
|
||||
|
||||
|
|
@ -194,10 +194,14 @@ export default class DashboardStore {
|
|||
|
||||
selectDefaultDashboard = () => {
|
||||
const pinnedDashboard = this.dashboards.find(d => d.isPinned)
|
||||
if (pinnedDashboard) {
|
||||
this.selectedDashboard = pinnedDashboard
|
||||
if (this.dashboards.length > 0) {
|
||||
if (pinnedDashboard) {
|
||||
this.selectedDashboard = pinnedDashboard
|
||||
} else {
|
||||
this.selectedDashboard = this.dashboards[0]
|
||||
}
|
||||
} else {
|
||||
this.selectedDashboard = this.dashboards[0]
|
||||
this.selectedDashboard = new Dashboard()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -228,6 +232,4 @@ const sampleDashboards = [
|
|||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
getRandomDashboard(),
|
||||
]
|
||||
12
frontend/app/components/ui/PageTitle/PageTitle.tsx
Normal file
12
frontend/app/components/ui/PageTitle/PageTitle.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
|
||||
function PageTitle({ title, className = '' }) {
|
||||
return (
|
||||
<h1 className={cn("text-2xl", className)}>
|
||||
{title}
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
|
||||
export default PageTitle;
|
||||
1
frontend/app/components/ui/PageTitle/index.ts
Normal file
1
frontend/app/components/ui/PageTitle/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './PageTitle';
|
||||
14
frontend/app/components/ui/SideMenuHeader/SideMenuHeader.tsx
Normal file
14
frontend/app/components/ui/SideMenuHeader/SideMenuHeader.tsx
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import stl from './sideMenuHeader.css';
|
||||
|
||||
function SideMenuHeader(props) {
|
||||
const { text, className } = props;
|
||||
return (
|
||||
<div className={ cn(className, stl.label, "uppercase color-gray") }>
|
||||
{ text }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SideMenuHeader;
|
||||
1
frontend/app/components/ui/SideMenuHeader/index.ts
Normal file
1
frontend/app/components/ui/SideMenuHeader/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default } from './SideMenuHeader';
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
.label {
|
||||
letter-spacing: 0.2em;
|
||||
color: gray;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ import { Icon, Popup } from 'UI';
|
|||
import cn from 'classnames';
|
||||
import stl from './sideMenuItem.css';
|
||||
|
||||
function SideMenuitem({ iconBg = false, iconColor = "gray-dark", iconSize = 18, className, iconName = 'info', title, active = false, disabled = false, onClick, deleteHandler, ...props }) {
|
||||
function SideMenuitem({ iconBg = false, iconColor = "gray-dark", iconSize = 18, className, iconName = null, title, active = false, disabled = false, onClick, deleteHandler, ...props }) {
|
||||
return (
|
||||
<Popup
|
||||
trigger={
|
||||
|
|
@ -18,10 +18,12 @@ function SideMenuitem({ iconBg = false, iconColor = "gray-dark", iconSize = 18,
|
|||
{...props}
|
||||
>
|
||||
<div className={ cn(stl.iconLabel, 'flex items-center', { [stl.disabled] : disabled })}>
|
||||
<div className="flex items-center justify-center w-8 h-8">
|
||||
<div className={cn({ "w-8 h-8 rounded-full relative opacity-20" : iconBg }, iconBg)} style={{ opacity: '0.2'}} />
|
||||
<Icon name={ iconName } size={ iconSize } color={active ? 'teal' : iconColor} className="absolute" />
|
||||
</div>
|
||||
{ iconName && (
|
||||
<div className="flex items-center justify-center w-8 h-8 mr-2">
|
||||
<div className={cn({ "w-8 h-8 rounded-full relative opacity-20" : iconBg }, iconBg)} style={{ opacity: '0.2'}} />
|
||||
<Icon name={ iconName } size={ iconSize } color={active ? 'teal' : iconColor} className="absolute" />
|
||||
</div>
|
||||
)}
|
||||
<span className={stl.title}>{ title }</span>
|
||||
</div>
|
||||
{deleteHandler &&
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-left: 10px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,5 +55,7 @@ export { default as HighlightCode } from './HighlightCode';
|
|||
export { default as NoPermission } from './NoPermission';
|
||||
export { default as NoSessionPermission } from './NoSessionPermission';
|
||||
export { default as HelpText } from './HelpText';
|
||||
export { default as SideMenuHeader } from './SideMenuHeader';
|
||||
export { default as PageTitle } from './PageTitle';
|
||||
|
||||
export { Input, Modal, Form, Message, Card } from 'semantic-ui-react';
|
||||
|
|
|
|||
3
frontend/app/svg/icons/bar-chart-line.svg
Normal file
3
frontend/app/svg/icons/bar-chart-line.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bar-chart-line" viewBox="0 0 16 16">
|
||||
<path d="M11 2a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v12h.5a.5.5 0 0 1 0 1H.5a.5.5 0 0 1 0-1H1v-3a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3h1V7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7h1V2zm1 12h2V2h-2v12zm-3 0V7H7v7h2zm-5 0v-3H2v3h2z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 351 B |
Loading…
Add table
Reference in a new issue