Skip to content

Commit

Permalink
recreate udtab component & fixes #1169 (#1422)
Browse files Browse the repository at this point in the history
* recreate udtab component & fixes #1169

* Merge

Co-authored-by: Adam Driscoll <adamdriscoll@users.noreply.github.com>
  • Loading branch information
AlonGvili and adamdriscoll committed Jan 6, 2020
1 parent 50d6aa8 commit 95a88de
Show file tree
Hide file tree
Showing 15 changed files with 8,265 additions and 6,291 deletions.
4,850 changes: 2,171 additions & 2,679 deletions src/UniversalDashboard.MaterialUI/package-lock.json

Large diffs are not rendered by default.

60 changes: 30 additions & 30 deletions src/UniversalDashboard.MaterialUI/package.json
Expand Up @@ -11,39 +11,39 @@
"author": "",
"license": "ISC",
"dependencies": {
"@material-ui/core": "^3.9.3",
"@material-ui/icons": "^3.0.2",
"@material-ui/lab": "^3.0.0-alpha.30",
"@material-ui/system": "^3.0.0-alpha.2",
"@material-ui/core": "^4.8.2",
"@material-ui/icons": "^4.5.1",
"@material-ui/lab": "^4.0.0-alpha.38",
"@material-ui/system": "^4.7.1",
"classnames": "^2.2.6",
"eslint-loader": "^2.1.2",
"react-interval": "^2.0.2",
"react-pdf": "^4.0.5",
"typeface-roboto": "0.0.54",
"typeface-roboto-condensed": "0.0.54"
"eslint-loader": "^3.0.3",
"react-interval": "^2.1.1",
"react-pdf": "^4.1.0",
"typeface-roboto": "0.0.75",
"typeface-roboto-condensed": "0.0.75"
},
"devDependencies": {
"@babel/core": "7.4.3",
"@babel/plugin-proposal-class-properties": "^7.4.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-react-constant-elements": "^7.2.0",
"@babel/plugin-transform-react-jsx-source": "^7.2.0",
"@babel/plugin-transform-runtime": "^7.4.3",
"@babel/polyfill": "^7.4.3",
"@babel/preset-env": "7.4.3",
"@babel/preset-react": "7.0.0",
"babel-eslint": "^10.0.1",
"babel-loader": "8.0.5",
"babel-plugin-minify-dead-code-elimination": "^0.5.0",
"babel-preset-react-app": "^7.0.2",
"css-loader": "^2.1.1",
"eslint": "^5.16.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-react": "^7.12.4",
"file-loader": "^3.0.1",
"@babel/core": "7.7.7",
"@babel/plugin-proposal-class-properties": "^7.7.4",
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/plugin-transform-react-constant-elements": "^7.7.4",
"@babel/plugin-transform-react-jsx-source": "^7.7.4",
"@babel/plugin-transform-runtime": "^7.7.6",
"@babel/polyfill": "^7.7.0",
"@babel/preset-env": "7.7.7",
"@babel/preset-react": "7.7.4",
"babel-eslint": "^10.0.3",
"babel-loader": "8.0.6",
"babel-plugin-minify-dead-code-elimination": "^0.5.1",
"babel-preset-react-app": "^9.1.0",
"css-loader": "^3.4.1",
"eslint": "^6.8.0",
"eslint-plugin-import": "^2.19.1",
"eslint-plugin-react": "^7.17.0",
"file-loader": "^5.0.2",
"remove-webpack-plugin": "^1.2.2",
"uglifyjs-webpack-plugin": "^2.1.2",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0"
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10"
}
}
119 changes: 58 additions & 61 deletions src/UniversalDashboard.Materialize/Components/index.js
@@ -1,6 +1,7 @@
import React, { useState, Suspense } from 'react';

require('materialize-css/dist/css/materialize.min.css');
require('material-components-web/dist/material-components-web.min.css');

import TabContainer from './tabs';
import UDButton from './ud-button';
Expand Down Expand Up @@ -60,39 +61,36 @@ UniversalDashboard.register("ud-fab", UDFab);
UniversalDashboard.register("ud-treeview", UDTreeView);
UniversalDashboard.register("loading", Loading);

function getDefaultHomePage(dashboard)
{
return dashboard.pages.find(function(page){
function getDefaultHomePage(dashboard) {
return dashboard.pages.find(function (page) {
return page.defaultHomePage === true;
});
}

function redirectToHomePage(dashboard)
{
function redirectToHomePage(dashboard) {
var defaultHomePage = getDefaultHomePage(dashboard);
if(defaultHomePage == null){

if (defaultHomePage == null) {
defaultHomePage = dashboard.pages[0];
}

if(defaultHomePage != null && defaultHomePage.url == null){
return <Redirect to={window.baseUrl + `/${defaultHomePage.name.replace(/ /g,"-")}`}/>
if (defaultHomePage != null && defaultHomePage.url == null) {
return <Redirect to={window.baseUrl + `/${defaultHomePage.name.replace(/ /g, "-")}`} />
}
else if (defaultHomePage.url != null && defaultHomePage.url.indexOf(":") === -1) {
return <Redirect to={defaultHomePage.url}/>
return <Redirect to={defaultHomePage.url} />
}
else if (defaultHomePage.name == null) {
return <Suspense fallback={<div></div>}>
<UDErrorCard message="Your first page needs to be a static page or a dynamic page without a variable in the URL." />
</Suspense>
<UDErrorCard message="Your first page needs to be a static page or a dynamic page without a variable in the URL." />
</Suspense>
}
else {
return <Redirect to={window.baseUrl + `/${defaultHomePage.name.replace(/ /g,"-")}`}/>
return <Redirect to={window.baseUrl + `/${defaultHomePage.name.replace(/ /g, "-")}`} />
}
}

class Materialize extends React.Component
{
class Materialize extends React.Component {
constructor(props) {
super(props);

Expand All @@ -103,7 +101,7 @@ class Materialize extends React.Component
}

setTitle(title) {
this.setState({title});
this.setState({ title });
}

togglePageCycle() {
Expand All @@ -112,66 +110,65 @@ class Materialize extends React.Component
})
}

render()
{
var {dashboard} = this.props;
render() {
var { dashboard } = this.props;

var component = this;

var dynamicPages = dashboard.pages.map(function(x) {
var dynamicPages = dashboard.pages.map(function (x) {
if (!x.dynamic) return null;

if (!x.url.startsWith("/")) {
x.url = "/" + x.url;
}

return <Route key={x.url} path={window.baseUrl + x.url} render={props => (
<UdPage onTitleChanged={component.setTitle.bind(component)} id={x.id} dynamic={true} {...props} autoRefresh={x.autoRefresh} refreshInterval={x.refreshInterval} key={props.location.key}/>
<UdPage onTitleChanged={component.setTitle.bind(component)} id={x.id} dynamic={true} {...props} autoRefresh={x.autoRefresh} refreshInterval={x.refreshInterval} key={props.location.key} />
)} />
})
var staticPages = dashboard.pages.map(function(x) {

var staticPages = dashboard.pages.map(function (x) {
if (x.dynamic) return null;

return <Route key={x.name} exact path={window.baseUrl + '/' + x.name.replace(/ /g, "-")} render={props => (
<UdPage onTitleChanged={component.setTitle.bind(component)} dynamic={false} {...x} {...props} autoRefresh={x.autoRefresh} refreshInterval={x.refreshInterval} key={props.location.key}/>
<UdPage onTitleChanged={component.setTitle.bind(component)} dynamic={false} {...x} {...props} autoRefresh={x.autoRefresh} refreshInterval={x.refreshInterval} key={props.location.key} />
)} />
})

return [<header>
<UDNavbar backgroundColor={dashboard.navBarColor}
fontColor={dashboard.navBarFontColor}
text={this.state.title}
links={dashboard.navbarLinks}
logo={dashboard.navBarLogo}
pages={dashboard.pages}
togglePaused={this.togglePageCycle.bind(this)}
showPauseToggle={dashboard.cyclePages}
history={this.props.history}
navigation={dashboard.navigation}
/>
</header>,
<main style={{background: dashboard.backgroundColor, color: dashboard.fontColor}}>
<Suspense fallback={<span/>}>
<Switch>
{staticPages}
{dynamicPages}
<Route exact path={window.baseUrl + `/`} render={() => redirectToHomePage(dashboard)} />
<Route path={window.baseUrl + `/`} render={() => <NotFound/>} />
</Switch>
</Suspense>
</main>,
<Suspense fallback={<div></div>}>
<UDModal />
</Suspense>,
<UdFooter backgroundColor={dashboard.navBarColor} fontColor={dashboard.navBarFontColor} footer={dashboard.footer} />,
<Route path={window.baseUrl + `/`} render={function (x) {
return <Suspense fallback={<div></div>}>
<PageCycler history={x.history} pages={dashboard.pages} cyclePages={dashboard.cyclePages && !this.state.pausePageCycle} cyclePagesInterval={dashboard.cyclePagesInterval} />
</Suspense>
}.bind(this)}
/>]
<UDNavbar backgroundColor={dashboard.navBarColor}
fontColor={dashboard.navBarFontColor}
text={this.state.title}
links={dashboard.navbarLinks}
logo={dashboard.navBarLogo}
pages={dashboard.pages}
togglePaused={this.togglePageCycle.bind(this)}
showPauseToggle={dashboard.cyclePages}
history={this.props.history}
navigation={dashboard.navigation}
/>
</header>,
<main style={{ background: dashboard.backgroundColor, color: dashboard.fontColor }}>
<Suspense fallback={<span />}>
<Switch>
{staticPages}
{dynamicPages}
<Route exact path={window.baseUrl + `/`} render={() => redirectToHomePage(dashboard)} />
<Route path={window.baseUrl + `/`} render={() => <NotFound />} />
</Switch>
</Suspense>
</main>,
<Suspense fallback={<div></div>}>
<UDModal />
</Suspense>,
<UdFooter backgroundColor={dashboard.navBarColor} fontColor={dashboard.navBarFontColor} footer={dashboard.footer} />,
<Route path={window.baseUrl + `/`} render={function (x) {
return <Suspense fallback={<div></div>}>
<PageCycler history={x.history} pages={dashboard.pages} cyclePages={dashboard.cyclePages && !this.state.pausePageCycle} cyclePagesInterval={dashboard.cyclePagesInterval} />
</Suspense>
}.bind(this)}
/>]
}
}

UniversalDashboard.renderDashboard = ({dashboard, history}) => <Materialize dashboard={dashboard} history={history} />;
UniversalDashboard.renderDashboard = ({ dashboard, history }) => <Materialize dashboard={dashboard} history={history} />;
53 changes: 53 additions & 0 deletions src/UniversalDashboard.Materialize/Components/tab.jsx
@@ -0,0 +1,53 @@
import React, { useEffect, useState, useRef } from 'react';
import Tab from 'react-materialize/lib/Tab'

const SET_STATE = "setState";
const REQUEST_STATE = "requestState";
const REMOVE_ELEMENT = "removeElement";
const ADD_ELEMENT = "addElement";
const CLEAR_ELEMENT = "clearElement";
const SYNC_ELEMENT = "syncElement";

const UDTab = props => {
const [tabContent, setTabContent] = useState(props.content)
const tabRef = useRef()
useEffect(() => {
console.log('udtab', props)
const pubSubToken = UniversalDashboard.subscribe(props.id, events);
return () => UniversalDashboard.unsubscribe(pubSubToken);
}, [props.id]);

const events = (msg, event) => {
switch (event.type) {
case SYNC_ELEMENT:
UniversalDashboard.get(
`/api/internal/component/element/${props.id}`,
data =>
setTabContent(data)
);
break;
default:
break;
}
}

const reload = () => {
UniversalDashboard.get(
`/api/internal/component/element/${props.id}`,
data =>
setTabContent(data)
)
}
return <Tab
options={{
duration: 300,
onShow: props.isEndpoint ? reload : null,
responsiveThreshold: Infinity,
swipeable: false
}}
title={`${props.title}`}>
{UniversalDashboard.renderComponent(tabContent)}
</Tab>
}

export default UDTab
83 changes: 36 additions & 47 deletions src/UniversalDashboard.Materialize/Components/tabs.jsx
@@ -1,54 +1,43 @@
import React, { Fragment } from 'react';
import M from 'materialize-css';
import React, { useEffect, useState } from 'react';
import { TabBar, Tab } from '@rmwc/tabs'

export default class TabContainer extends React.Component {

componentDidMount() {
M.Tabs.init(this.element);
var instance = M.Tabs.getInstance(this.element);
instance.updateTabIndicator();
}

renderTabHeaders() {

var tabIndex = 0;

return this.props.tabs.map(x => {
tabIndex++;
return (
<li class="tab"><a href={`#${this.props.id}${tabIndex}`}>{x.text}</a></li>
)
});
}
const TabPanel = ({ content, ...props }) => {
console.log('TabPanel Props: ', props)
console.log('TabPanel Content: ', content)
return <div>{UniversalDashboard.renderComponent(content)}</div>
}

renderTabContent() {
var tabIndex = 0;
const TabContainer = props => {
const { tabs } = props
const [activeTabIndex, setActiveTabIndex] = useState(0)
const [activeTabPanel, setActiveTabPanel] = useState(tabs[0])

return this.props.tabs.map(x => {
tabIndex++;
return (
<div id={`${this.props.id}${tabIndex}`} className="col s12">
{UniversalDashboard.renderComponent(x.content)}
</div>
)
});
const refreshTabPanel = (id, tab) => {
UniversalDashboard.get(`/api/internal/component/element/${id}`, data => {
setActiveTabPanel({ ...tab, content: data })
})
}

render() {
var headers = this.renderTabHeaders();
var content = this.renderTabContent();

return (
<Fragment>
<div>
<ul className="tabs" ref={x => this.element = x}>
{headers}
</ul>
</div>
{content}
</Fragment>

)
}
return (
<div>
<TabBar
activeTabIndex={activeTabIndex}
onActivate={evt => setActiveTabIndex(evt.detail.index)}
>
{
tabs.map(tab => <Tab
id={tab.id}
label={tab.label}
stacked={tab.icon && tab.stacked || undefined}
onInteraction={evt => tab.refreshWhenActive && tab.isEndpoint ? refreshTabPanel(evt.detail.tabId, tab) : setActiveTabPanel(tab)}
icon={tab.icon && UniversalDashboard.renderComponent(tab.icon)} />
)
}
</TabBar>
<TabPanel {...activeTabPanel} />
</div>
)
}

export default TabContainer

1 comment on commit 95a88de

@adamdriscoll
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit has been mentioned on Ironman Software Forums. There might be relevant details there:

https://forums.universaldashboard.io/t/bug-in-default-theme-for-release-nightly-build-20200106-4/1938/4

Please sign in to comment.