Bladeren bron

Beginning of HTML+Bootstrap+React UI for new desktop client -- looking like it will be easier than retrofitting the old Qt client for the new API.

Adam Ierymenko 10 jaren geleden
bovenliggende
commit
b2b32e5969
12 gewijzigde bestanden met toevoegingen van 2777 en 31 verwijderingen
  1. 32 29
      service/ControlPlane.cpp
  2. 2 1
      service/ControlPlane.hpp
  3. 1 1
      service/OneService.cpp
  4. 2606 0
      ui/JSXTransformer.js
  5. 51 0
      ui/ZeroTierNode.jsx
  6. 4 0
      ui/bootstrap-theme.min.css
  7. 4 0
      ui/bootstrap.min.css
  8. 22 0
      ui/index.html
  9. 4 0
      ui/main.jsx
  10. 11 0
      ui/react.min.js
  11. 1 0
      ui/simpleajax.min.js
  12. 39 0
      ui/zerotier.css

+ 32 - 29
service/ControlPlane.cpp

@@ -37,8 +37,7 @@
 #include "../node/InetAddress.hpp"
 #include "../node/Node.hpp"
 #include "../node/Utils.hpp"
-
-#define ZT_BUILD_IN_WEB_UI
+#include "../osdep/OSUtils.hpp"
 
 namespace ZeroTier {
 
@@ -242,9 +241,10 @@ static void _jsonAppend(unsigned int depth,std::string &buf,const ZT1_Peer *peer
 	buf.append(json);
 }
 
-ControlPlane::ControlPlane(OneService *svc,Node *n) :
+ControlPlane::ControlPlane(OneService *svc,Node *n,const char *uiStaticPath) :
 	_svc(svc),
-	_node(n)
+	_node(n),
+	_uiStaticPath((uiStaticPath) ? uiStaticPath : "")
 {
 }
 
@@ -316,31 +316,34 @@ unsigned int ControlPlane::handleRequest(
 			 * dot in the first path element (e.g. foo.html) is considered a static page,
 			 * as nothing in the API is so named. */
 
-#ifdef ZT_BUILD_IN_WEB_UI
-			if (ext == ".html")
-				responseContentType = "text/html";
-			else if (ext == ".js")
-				responseContentType = "application/javascript";
-			else if (ext == ".json")
-				responseContentType = "application/json";
-			else if (ext == ".css")
-				responseContentType = "text/css";
-			else if (ext == ".png")
-				responseContentType = "image/png";
-			else if (ext == ".jpg")
-				responseContentType = "image/jpeg";
-			else if (ext == ".gif")
-				responseContentType = "image/gif";
-			else if (ext == ".txt")
-				responseContentType = "text/plain";
-			else if (ext == ".xml")
-				responseContentType = "text/xml";
-			else if (ext == ".svg")
-				responseContentType = "image/svg+xml";
-			else responseContentType = "application/octet-stream";
-			responseBody = "<html><body>Hello World!</body></html>";
-			scode = 200;
-#endif // ZT_BUILD_IN_WEB_UI
+			if (_uiStaticPath.length() > 0) {
+				if (ext == ".html")
+					responseContentType = "text/html";
+				else if (ext == ".js")
+					responseContentType = "application/javascript";
+				else if (ext == ".jsx")
+					responseContentType = "text/jsx";
+				else if (ext == ".json")
+					responseContentType = "application/json";
+				else if (ext == ".css")
+					responseContentType = "text/css";
+				else if (ext == ".png")
+					responseContentType = "image/png";
+				else if (ext == ".jpg")
+					responseContentType = "image/jpeg";
+				else if (ext == ".gif")
+					responseContentType = "image/gif";
+				else if (ext == ".txt")
+					responseContentType = "text/plain";
+				else if (ext == ".xml")
+					responseContentType = "text/xml";
+				else if (ext == ".svg")
+					responseContentType = "image/svg+xml";
+				else responseContentType = "application/octet-stream";
+				scode = OSUtils::readFile((_uiStaticPath + ZT_PATH_SEPARATOR_S + ps[0]).c_str(),responseBody) ? 200 : 404;
+			} else {
+				scode = 404;
+			}
 
 		} else if (isAuth) {
 			/* Things that require authentication -- a.k.a. everything but static web app pages. */

+ 2 - 1
service/ControlPlane.hpp

@@ -49,7 +49,7 @@ struct InetAddress;
 class ControlPlane
 {
 public:
-	ControlPlane(OneService *svc,Node *n);
+	ControlPlane(OneService *svc,Node *n,const char *uiStaticPath);
 	~ControlPlane();
 
 	/**
@@ -102,6 +102,7 @@ public:
 private:
 	OneService *const _svc;
 	Node *const _node;
+	std::string _uiStaticPath;
 	std::set<std::string> _authTokens;
 	std::map<std::string,ControlPlaneSubsystem *> _subsystems;
 	Mutex _lock;

+ 1 - 1
service/OneService.cpp

@@ -226,7 +226,7 @@ public:
 			if (_master)
 				_node->setNetconfMaster((void *)_master);
 
-			_controlPlane = new ControlPlane(this,_node);
+			_controlPlane = new ControlPlane(this,_node,(_homePath + ZT_PATH_SEPARATOR_S + "ui").c_str());
 			_controlPlane->addAuthToken(authToken.c_str());
 			if (_master)
 				_controlPlane->mount("controller",reinterpret_cast<ControlPlaneSubsystem *>(_master));

File diff suppressed because it is too large
+ 2606 - 0
ui/JSXTransformer.js


+ 51 - 0
ui/ZeroTierNode.jsx

@@ -0,0 +1,51 @@
+var ZeroTierNode = React.createClass({
+	getInitialState: function() {
+		return {
+			address: '----------',
+			online: false,
+			version: '_._._'
+		};
+	},
+
+	updateAll: function() {
+		Ajax.call({
+			url: 'status?auth='+this.props.authToken,
+			cache: false,
+			type: 'GET',
+			success: function(data) {
+				if (data)
+					this.setState(JSON.parse(data));
+			}.bind(this),
+			error: function() {
+				this.setState(this.getInitialState());
+			}.bind(this)
+		})
+	},
+
+	componentDidMount: function() {
+		this.updateAll();
+//		this.updateIntervalId = setInterval(this.updateAll,2500);
+	},
+	componentWillUnmount: function() {
+//		clearInterval(this.updateIntervalId);
+	},
+	render: function() {
+		return (
+			<div className="container-fluid zeroTierNode">
+				<div className="row">
+				</div>
+				<div className="row">
+					<div className="col-xs-8">
+						<span className="zerotier-address">{this.state.address}</span>
+						<span className="zerotier-node-statusline">{this.state.online ? 'ONLINE' : 'OFFLINE'}&nbsp;&nbsp;{this.state.version}</span>
+					</div>
+					<div className="col-xs-4">
+						<form>
+							<input type="text"/>
+						</form>
+					</div>
+				</div>
+			</div>
+		);
+	}
+});

File diff suppressed because it is too large
+ 4 - 0
ui/bootstrap-theme.min.css


File diff suppressed because it is too large
+ 4 - 0
ui/bootstrap.min.css


+ 22 - 0
ui/index.html

@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<title>ZeroTier One</title>
+	<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<link rel="stylesheet" href="bootstrap.min.css">
+	<link rel="stylesheet" href="bootstrap-theme.min.css">
+	<link rel="stylesheet" href="zerotier.css">
+
+	<script src="simpleajax.min.js"></script>
+	<script src="react.min.js"></script>
+	<script src="JSXTransformer.js"></script>
+
+	<script type="text/jsx" src="ZeroTierNode.jsx"></script>
+
+	<script type="text/jsx" src="main.jsx"></script>
+</head>
+<body>
+<div style="width: 100%; height: 100%;" id="main"></div>
+</body>
+</html>

+ 4 - 0
ui/main.jsx

@@ -0,0 +1,4 @@
+React.render(
+	<ZeroTierNode authToken={'5d6181b71fae2684f9cc64ed'} />,
+	document.getElementById('main')
+);

File diff suppressed because it is too large
+ 11 - 0
ui/react.min.js


File diff suppressed because it is too large
+ 1 - 0
ui/simpleajax.min.js


+ 39 - 0
ui/zerotier.css

@@ -0,0 +1,39 @@
+/* Dark blue-grey: #234447
+ * Light blue-grey: #91a2a3
+ * Light yellow: #ffffcc
+ * Orange: #ffb354 */
+
+/*
+@font-face {
+	font-family: 'Clear Sans Thin';
+	src: url('fonts/clearsans_thin/ClearSans-Thin-webfont.eot');
+	src: url('fonts/clearsans_thin/ClearSans-Thin-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/clearsans_thin/ClearSans-Thin-webfont.woff') format('woff'), url('fonts/clearsans_thin/ClearSans-Thin-webfont.ttf') format('truetype'), url('fonts/clearsans_thin/ClearSans-Thin-webfont.svg#clear_sans_thinregular') format('svg');
+	font-weight: normal;
+	font-style: normal;
+}
+*/
+/*
+@font-face {
+	font-family: 'Clear Sans Regular';
+	src: url('ClearSans-Regular-webfont.eot');
+	src: url('ClearSans-Regular-webfont.eot?#iefix') format('embedded-opentype'), url('ClearSans-Regular-webfont.woff') format('woff'), url('ClearSans-Regular-webfont.ttf') format('truetype'), url('ClearSans-Regular-webfont.svg#clear_sansregular') format('svg');
+	font-weight: normal;
+	font-style: normal;
+}
+*/
+
+html,body {
+	font-family: "Helvetica Neue","Lucida Sans Unicode",sans-serif;
+	font-size: 12pt;
+	margin: 0;
+	padding: 0;
+	width: 100%;
+}
+
+.zerotier-address {
+	font-family: monospace;
+}
+.zerotier-node-statusline {
+	font-size: smaller;
+	padding: 0 0.75rem 0 0.75rem;
+}

Some files were not shown because too many files changed in this diff