Skip to content

Commit

Permalink
simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
deliciousmonster committed Sep 17, 2018
1 parent 796a575 commit 9d519fc
Show file tree
Hide file tree
Showing 17 changed files with 2,273 additions and 5,055 deletions.
4 changes: 3 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"max-len": 0,
"object-curly-newline": 0,
"no-return-assign": 0,
"no-nested-ternary": 0
"no-nested-ternary": 0,
"react/jsx-one-expression-per-line": 0,
"react/prop-types": 0
}
}
55 changes: 12 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# nio UI Scaffold
The easiest way to create a nio-powered UI is to start with our [UI scaffold](https://github.com/niolabs/ui-scaffold). It gets you up and running in minutes.

---

## What’s in the box

Expand All @@ -12,12 +11,10 @@ The easiest way to create a nio-powered UI is to start with our [UI scaffold](ht
- Third party software (click to review each library's licensing)
- [ReactJS](https://reactjs.org/) site scaffold
- [react-router](https://reacttraining.com/react-router/) for navigation
- [webpack 3](https://webpack.js.org/) module bundling and development webserver
- [auth0](https://auth0.com/) for securing the site (optional, default false)
- [webpack 4](https://webpack.js.org/) module bundling and development webserver

If you’re at all familiar with React, this simple example covers most of what you need to know to get started.

---

## Hello world (what time is it?)

Expand All @@ -30,7 +27,7 @@ Follow these steps to create a simple UI that can publish to, subscribe to, and
npm i -s
```
1. In the root of the project, rename `config.js.example` to `config.js`.
1. In the root of the project, rename `config.js.example` to `config.js`, and fill out the pubkeeper server details from your pubkeeper server instance (see *Configuring Your Pubkeeper Server* below)
1. Start the project.
```
Expand All @@ -40,60 +37,34 @@ Follow these steps to create a simple UI that can publish to, subscribe to, and
1. Visit the project at https://0.0.0.0:3000.
- The development web server uses a self-signed certificate, and you may see a warning about the site being insecure. In your local development environment, it is safe to click "Advanced" > "proceed to site anyway."
1. You'll be prompted to log into your **nio** account to choose which Pubkeeper Server your project should use
- If you see a message saying the application can't find any systems, follow the instructions [here](/system-designer/designer-tasks.html) to create one.
You’ll see a simple UI with a clock that updates every second.
### What’s actually happening?
- The UI connects to your cloud Pubkeeper server.
- When the main page renders, it sets a local variable of the current time and sets an interval to update that time every second.
- The Pubkeeper brewer publishes the time to the topic “ui_scaffold.example_brew”.
- The Pubkeeper patron subscribes to “ui_scaffold.example_brew” topic, receives the data, and delivers it to the handler `writeDataToOutput`, which sets the local state variable `time` equal to the inbound time.
- The React `Clock` component from the nio UI Kit then renders itself based on the inbound time.
Sure, you could have just had the timer set the local state variable, but then you wouldn’t have become such an expert at using Pubkeeper.
## What’s actually happening?
---
- The PubkeeperContext (providers > pubkeeper.js) uses React's Context API to asyncronously connect to the Pubkeeper server and continually ingest data into the PubkeeperProvider Context Object.
- It creates a Brewer that publishes the time to the topic “ui_scaffold.example_brew” every second.
- It creates a Pubkeeper Patron that subscribes to “ui_scaffold.example_brew” topic.
- The Patron receives the data, and delivers it to the handler `writeDataToOutput`, which sets the local state variable `providerData` equal to an object containing `time` (a js Date object), and `timeHistory` (an array of all previous times received).
- The Homepage uses the PubkeeperContext.Consumer to render the providerData.time value to the React `Clock` component from the nio UI Kit, which then renders itself based on the inbound time.
- Page 2 uses the PubkeeperContext.Consumer to render the providerData.timeHistory array into a textbox.
## Going public
The UI Scaffold is set up to make local development fast and easy out of the box. This includes selecting your Pubkeeper Server for you by having you log in.
Sure, you could have just had the timer set the local state variable, but then you wouldn’t have become such an expert at using Pubkeeper.
#### Static Pubkeeper Server
Of course, your **nio** app publishes only to your Pubkeeper server, so you'll want to configure a **Static Pubkeeper Server**:
## Configuring Pubkeeper Server
1. Get your Pubkeeper **hostname** and **token** from your nio-managed cloud-instance:
1. Open the nio **System Designer** in a browser: https://designer.n.io/.
1. Select your system in the left-hand navigation.
1. Click the **edit** button in the contextual toolbar to open its configuration.
1. Open `config.js`
1. Set `staticPubkeeper` to **true**.
1. Set `PK_HOST` to your **hostname** value.
1. Set `PK_JWT` to your **token** value.
1. Set `WS_HOST` to your **hostname** value, but swap the word 'pubkeeper' for 'websocket'.
1. e.g.- if your **hostname** is `aaaaa.pubkeeper.nio.works`, use `aaaaa.websocket.nio.works`.
#### Authentication (optional)
By default, the auth0 configuration provided in `config.js` is used to log users into **nio** and fetch their Pubkeeper server details. **This will only work if you're running the site locally, at https://0.0.0.0:3000**.
Once you configure the site to use a **Static Pubkeeper Server**, users won't need to log in.
If you would like to require that users log in to access your app, you can leverage the auth0 authentication engine for that very purpose:
1. Go to https://auth0.com and **Sign Up**.
1. Once you complete the signup process, you'll be taken to your dashboard.
1. Choose Clients > Settings
1. In `config.js`, replace **webAuth** Domain and Client ID with your own, and set Audience to **false**.
1. In Auth0, set the Client Type to **Single Page Application**
1. In Auth0, enter `https://0.0.0.0:3000?authorize=true` into **Allowed Callback URLs**
1. In Auth0, enter `https://0.0.0.0:3000` into **Allowed Logout URLs**.
- (You'll want to add your public URL to these boxes before you go live, of course.)
----------------
## What’s next?
The output of any service that shares the same Pubkeeper host and token that you configured above can be consumed by your UI. All you need to do is update the patron’s topic (or add new patrons!), register a handler, and render the data.
Expand All @@ -105,9 +76,7 @@ Of course, if React isn’t your thing, the Pubkeeper browser client can be used
npm i -s @pubkeeper/browser-client
```
---
### Apache 2.0 License
## Apache 2.0 License
Copyright 2017-2018 n.io innovation, LLC
Expand Down
4 changes: 2 additions & 2 deletions assets/app.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@import '~@nio/ui-kit/dist/nio';
@import '~font-awesome/css/font-awesome.min.css';
@import './css/vars';
@import './css/base';

Expand All @@ -8,7 +7,8 @@

#demo_output{
border: 1px solid #e6e9ee;
height: 150px;
height: 160px;
border-radius: 4px;
overflow-y: auto;
padding: 10px;
}
5 changes: 2 additions & 3 deletions assets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from '../components/app';
import { PubkeeperProvider } from '../providers/pubkeeper';

require('whatwg-fetch');

render((<BrowserRouter><App /></BrowserRouter>), document.getElementById('app'));
render((<PubkeeperProvider><BrowserRouter><App /></BrowserRouter></PubkeeperProvider>), document.getElementById('app'));
82 changes: 10 additions & 72 deletions components/app.js
Original file line number Diff line number Diff line change
@@ -1,98 +1,36 @@
import React from 'react';
import { Navbar, NavbarToggler, Nav, NavItem, Collapse, NavLink as DumbNavLink } from '@nio/ui-kit';
import React, { Component } from 'react';
import { Navbar, NavbarToggler, Nav, NavItem, Collapse } from '@nio/ui-kit';
import { NavLink } from 'react-router-dom';

import '../assets/app.scss';
import Routes from './routes';
import ConfigModal from './configModal';
import { isAuthenticated, authRequired, handleAuthentication, login, logout } from '../util/auth';
import { staticPubkeeper } from '../util/pubkeeper';

class App extends React.Component {
constructor(props) {
super(props);
this.state = { navOpen: false, configOpen: false };
const fns = ['toggleNav', 'openConfig', 'closeConfig', 'forceRender'];
fns.forEach((fn) => { this[fn] = this[fn].bind(this); });
}

componentDidMount() {
if (window.location.search.indexOf('authorize=true') >= 0) {
handleAuthentication().then(() => this.forceRender());
} else if (!isAuthenticated() && authRequired()) {
login();
}
}

forceRender() {
this.setState(this.state);
}

openConfig() {
this.setState({ configOpen: true });
}
class App extends Component {
state = { navOpen: false };

closeConfig() {
this.setState({ configOpen: false });
}
render = () => {
const { navOpen } = this.state;

toggleNav(close) {
this.setState({ navOpen: close ? false : !this.state.navOpen });
}

render() {
const { navOpen, configOpen } = this.state;
const auth = isAuthenticated();
const authrequired = authRequired();
const staticPK = staticPubkeeper();

return (auth || !authrequired) ? (
return (
<div>
<Navbar id="app-nav" dark fixed="top" expand="md">
<div className="navbar-brand">
<NavLink to="/"><div id="logo" /></NavLink>
</div>
<NavbarToggler right onClick={() => this.toggleNav()} isOpen={navOpen} />
<NavbarToggler right onClick={() => this.setState({ navOpen: !navOpen })} isOpen={navOpen} />
<Collapse isOpen={navOpen} navbar>
<Nav className="ml-auto" navbar>
<NavItem>
<NavLink onClick={this.toggleNav} exact to="/">Home</NavLink>
</NavItem>
<NavItem>
<NavLink onClick={this.toggleNav} exact to="/page2">Page 2</NavLink>
</NavItem>
<NavItem>
<NavLink onClick={this.toggleNav} exact to="/page3">Page 3</NavLink>
<NavLink onClick={() => this.setState({ navOpen: false })} exact to="/">Home</NavLink>
</NavItem>
{ !staticPK && (
<NavItem>
<DumbNavLink onClick={() => this.openConfig()} title="settings"><i className="fa fa-lg fa-gear" /></DumbNavLink>
</NavItem>
)}
{ (authrequired || auth) && (
auth ? (
<NavItem>
<DumbNavLink onClick={() => logout()} title="log out"><i className="fa fa-lg fa-sign-out" /></DumbNavLink>
</NavItem>
) : (
<NavItem>
<DumbNavLink onClick={() => login()} title="log in"><i className="fa fa-lg fa-sign-in" /></DumbNavLink>
</NavItem>
)
)}
</Nav>
</Collapse>
</Navbar>
<div id="app-container">
<Routes />
</div>
<ConfigModal
isOpen={configOpen}
openConfig={this.openConfig}
closeConfig={this.closeConfig}
/>
</div>
) : null;
);
}
}

Expand Down
Loading

0 comments on commit 9d519fc

Please sign in to comment.