feat(ui) - dashboards wip

This commit is contained in:
Shekar Siri 2022-03-18 15:40:29 +01:00
parent 38b536aae1
commit 391189e894
14 changed files with 114 additions and 20 deletions

View file

@ -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))
);

View file

@ -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);

View file

@ -0,0 +1 @@
export { default } from './DashboardSideMenu';

View file

@ -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));

View file

@ -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(),
]

View 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;

View file

@ -0,0 +1 @@
export { default } from './PageTitle';

View 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;

View file

@ -0,0 +1 @@
export { default } from './SideMenuHeader';

View file

@ -0,0 +1,4 @@
.label {
letter-spacing: 0.2em;
color: gray;
}

View file

@ -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 &&

View file

@ -28,7 +28,6 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-left: 10px;
margin-top: 1px;
}

View file

@ -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';

View 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