veyron/examples/pipetobrowser: Help page and polishing the error and loading
views.
Change-Id: Ia00e2e6c5bf699c12f941352bc237f90012271f0
diff --git a/examples/pipetobrowser/browser/actions/navigate-help.js b/examples/pipetobrowser/browser/actions/navigate-help.js
new file mode 100644
index 0000000..d2c0691
--- /dev/null
+++ b/examples/pipetobrowser/browser/actions/navigate-help.js
@@ -0,0 +1,43 @@
+/*
+ * Navigates to help page
+ * @fileoverview
+ */
+import { Logger } from 'libs/logs/logger'
+import { register, trigger } from 'libs/mvc/actions'
+
+import { state as publishState } from 'services/pipe-to-browser-server'
+
+import { page } from 'runtime/context'
+
+import { HelpView } from 'views/help/view'
+
+var log = new Logger('actions/navigate-help');
+const ACTION_NAME = 'help';
+
+/*
+ * Registers the action
+ */
+export function registerHelpAction() {
+ register(ACTION_NAME, actionHandler);
+}
+
+/*
+ * Triggers the action
+ */
+export function navigateHelp() {
+ return trigger(ACTION_NAME);
+}
+
+/*
+ * Handles the action.
+ *
+ * @private
+ */
+function actionHandler() {
+ log.debug('navigate help triggered');
+
+ // create a help view
+ var helpView = new HelpView(publishState);
+
+ page.setSubPageView('help', helpView);
+}
\ No newline at end of file
diff --git a/examples/pipetobrowser/browser/index.html b/examples/pipetobrowser/browser/index.html
index e37405b..a73e258 100644
--- a/examples/pipetobrowser/browser/index.html
+++ b/examples/pipetobrowser/browser/index.html
@@ -21,6 +21,7 @@
<link rel="import" href="views/pipes/component.html"/>
<link rel="import" href="views/redirect-pipe-dialog/component.html"/>
<link rel="import" href="views/neighborhood/component.html"/>
+ <link rel="import" href="views/help/component.html"/>
<link rel="import" href="libs/ui-components/blackhole/component.html"/>
diff --git a/examples/pipetobrowser/browser/libs/ui-components/blackhole/component.css b/examples/pipetobrowser/browser/libs/ui-components/blackhole/component.css
index 2dc25c7..b7c7a91 100644
--- a/examples/pipetobrowser/browser/libs/ui-components/blackhole/component.css
+++ b/examples/pipetobrowser/browser/libs/ui-components/blackhole/component.css
@@ -15,8 +15,8 @@
position: absolute;
top: 50%;
left: 50%;
- margin-left: -9px;
- margin-top: -9px;
+ margin-left: -14px;
+ margin-top: -14px;
}
.attribution {
diff --git a/examples/pipetobrowser/browser/libs/ui-components/common/spinner.gif b/examples/pipetobrowser/browser/libs/ui-components/common/spinner.gif
index d03237b..ebb7cad 100644
--- a/examples/pipetobrowser/browser/libs/ui-components/common/spinner.gif
+++ b/examples/pipetobrowser/browser/libs/ui-components/common/spinner.gif
Binary files differ
diff --git a/examples/pipetobrowser/browser/pipe-viewers/builtin/vlog/plugin.js b/examples/pipetobrowser/browser/pipe-viewers/builtin/vlog/plugin.js
index 67b1779..76d52a2 100644
--- a/examples/pipetobrowser/browser/pipe-viewers/builtin/vlog/plugin.js
+++ b/examples/pipetobrowser/browser/pipe-viewers/builtin/vlog/plugin.js
@@ -3,7 +3,7 @@
* Please note that Veyron writes logs to stderr stream, in *nix systems 2>&1
* can be used to redirect stderr to stdout which can be then piped to P2B.
* @tutorial myVeyronServerd -v=3 2>&1 | p2b google/p2b/[name]/vlog
- * @tutorial cat logfile.text | p2b google/p2b/[name]/vlog
+ * @tutorial cat logfile.txt | p2b google/p2b/[name]/vlog
* @fileoverview
*/
import { View } from 'view';
diff --git a/examples/pipetobrowser/browser/pipe-viewers/manager.js b/examples/pipetobrowser/browser/pipe-viewers/manager.js
index a97e96b..086dfc9 100644
--- a/examples/pipetobrowser/browser/pipe-viewers/manager.js
+++ b/examples/pipetobrowser/browser/pipe-viewers/manager.js
@@ -56,8 +56,9 @@
loadedPipeViewers[name] = pipeViewerClass;
return pipeViewerClass;
}).catch((e) => {
- log.debug('could not load viewer JavaScript module for:', name, e);
- return Promise.reject(e);
+ var errMessage = 'could not load viewer for: ' + name;
+ log.debug(errMessage, e);
+ return Promise.reject(new Error(errMessage));
})
}
diff --git a/examples/pipetobrowser/browser/runtime/app.js b/examples/pipetobrowser/browser/runtime/app.js
index d66ad2b..59e6b55 100644
--- a/examples/pipetobrowser/browser/runtime/app.js
+++ b/examples/pipetobrowser/browser/runtime/app.js
@@ -5,6 +5,7 @@
import { registerAddPipeViewerAction } from 'actions/add-pipe-viewer'
import { registerNavigatePipesPageAction, navigatePipesPage } from 'actions/navigate-pipes-page'
import { registerNavigateNeigbourhoodAction, navigateNeigbourhood } from 'actions/navigate-neighborhood'
+import { registerHelpAction, navigateHelp } from 'actions/navigate-help'
import { registerRedirectPipeAction } from 'actions/redirect-pipe'
import { SubPageItem } from 'views/page/view'
@@ -44,6 +45,7 @@
registerNavigatePipesPageAction();
registerNavigateNeigbourhoodAction();
registerRedirectPipeAction();
+ registerHelpAction();
}
/*
@@ -75,9 +77,8 @@
var helpSubPageItem = new SubPageItem('help');
helpSubPageItem.name = 'Help';
helpSubPageItem.icon = 'help';
- helpSubPageItem.onActivate = function() {
- alert('Not Implemented');
- };
+ helpSubPageItem.onActivate = navigateHelp;
+
page.subPages.push(helpSubPageItem);
document.body.appendChild(page.element);
diff --git a/examples/pipetobrowser/browser/services/pipe-to-browser-server.js b/examples/pipetobrowser/browser/services/pipe-to-browser-server.js
index 21dc83e..16cc738 100644
--- a/examples/pipetobrowser/browser/services/pipe-to-browser-server.js
+++ b/examples/pipetobrowser/browser/services/pipe-to-browser-server.js
@@ -32,12 +32,12 @@
/*
* Publishes the p2b service under google/p2b/{name}
- * e.g. If name is "JohnTablet", p2b service will be accessible under name:
- * 'google/p2b/JohnTablet'
+ * e.g. If name is "john-tablet", p2b service will be accessible under name:
+ * 'google/p2b/john-tablet'
*
* pipe() method can be invoked on any 'google/p2b/{name}/suffix' name where
* suffix identifies the viewer that can format and display the stream data
- * e.g. 'google/p2b/JohnTablet/DataTable'.pipe() will display the incoming
+ * e.g. 'google/p2b/john-tablet/console'.pipe() will display the incoming
* data in a data table. See /app/viewer/ for a list of available viewers.
* @param {string} name Name to publish the service under
* @param {function} pipeRequestHandler A function that will be called when
@@ -55,8 +55,6 @@
var p2b = {
pipe($suffix, $stream) {
return new Promise(function(resolve, reject) {
- //TODO(aghassemi) publish-issue remove /pipe from the suffix
- $suffix = $suffix.substr(5);
log.debug('received pipe request for:', $suffix);
var numBytesForThisCall = 0;
diff --git a/examples/pipetobrowser/browser/views/error/broken_robot.png b/examples/pipetobrowser/browser/views/error/broken_robot.png
new file mode 100644
index 0000000..dc0b7f1
--- /dev/null
+++ b/examples/pipetobrowser/browser/views/error/broken_robot.png
Binary files differ
diff --git a/examples/pipetobrowser/browser/views/error/component.css b/examples/pipetobrowser/browser/views/error/component.css
new file mode 100644
index 0000000..94237b0
--- /dev/null
+++ b/examples/pipetobrowser/browser/views/error/component.css
@@ -0,0 +1,19 @@
+:host {
+ background-image: url('broken_robot.png');
+ background-repeat: no-repeat;
+ background-position: right 50%;
+ min-height: 300px;
+ width: 100%;
+ max-width: 600px;
+ display: block;
+}
+
+h2 {
+ font-size: 1.1em;
+}
+
+h3 {
+ font-size: 0.9em;
+ color: rgba(0,0,0,0.54);
+ margin-right: 100px;
+}
\ No newline at end of file
diff --git a/examples/pipetobrowser/browser/views/error/component.html b/examples/pipetobrowser/browser/views/error/component.html
index 3df3570..d746a14 100644
--- a/examples/pipetobrowser/browser/views/error/component.html
+++ b/examples/pipetobrowser/browser/views/error/component.html
@@ -2,7 +2,10 @@
<polymer-element name="p2b-error">
<template>
- <h1>error: {{errorMessage}}</h1>
+ <link rel="stylesheet" href="component.css">
+ <h2 page-title>Error</h2>
+ <h3>Sorry, some of the 1s and 0s got mixed.</h3>
+ <h3>{{errorMessage}}</h3>
</template>
<script>
Polymer('p2b-error', {
diff --git a/examples/pipetobrowser/browser/views/error/view.js b/examples/pipetobrowser/browser/views/error/view.js
index 3b9024f..c99c1d2 100644
--- a/examples/pipetobrowser/browser/views/error/view.js
+++ b/examples/pipetobrowser/browser/views/error/view.js
@@ -1,5 +1,8 @@
import { exists } from 'libs/utils/exists'
import { View } from 'libs/mvc/view'
+import { Logger } from 'libs/logs/logger'
+
+var log = new Logger('views/error');
/*
* View representing application error.
@@ -21,8 +24,9 @@
}
var errorMessage = err.toString();
+ log.debug(errorMessage);
if(exists(err.stack)) {
- errorMessage += err.stack;
+ log.debug(err.stack);
}
this.element.errorMessage = errorMessage;
diff --git a/examples/pipetobrowser/browser/views/help/component.css b/examples/pipetobrowser/browser/views/help/component.css
new file mode 100644
index 0000000..faf1990
--- /dev/null
+++ b/examples/pipetobrowser/browser/views/help/component.css
@@ -0,0 +1,32 @@
+.name {
+ font-weight: bold;
+ color: rgba(0, 0, 0, 0.8);
+}
+
+.mono, .code {
+ font-size: 1.1em;
+ font-family: monospace;
+}
+
+.code {
+ background-color: #222;
+ color: #fafafa;
+ padding: 1em;
+ white-space: normal;
+ word-break: break-all;
+}
+
+h3 {
+ font-size: 1.3em;
+}
+
+h4 {
+ font-size: 1.2em;
+ color: rgb(51, 103, 214);
+ margin-bottom: 0.5em;
+}
+
+a {
+ color: #5677fc;
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/examples/pipetobrowser/browser/views/help/component.html b/examples/pipetobrowser/browser/views/help/component.html
new file mode 100644
index 0000000..46e1d2c
--- /dev/null
+++ b/examples/pipetobrowser/browser/views/help/component.html
@@ -0,0 +1,64 @@
+<link rel="import" href="/libs/vendor/polymer/polymer/polymer.html">
+
+<polymer-element name="p2b-help">
+<template>
+ <link rel="stylesheet" href="component.css">
+ <link rel="stylesheet" href="../common/common.css">
+ <h2 page-title>Help</h2>
+ <p>Pipe To Browser allows you to pipe anything from shell console to the browser. Piped data is then displayed in a graphical and formatted way by a viewer you can specify.</p>
+ <h3>Getting Started</h3>
+ <template if="{{serviceState.published}}">
+ <p>Looks like you have already started the service under <span class="name">{{publishedName}}</span>, great!</p>
+ </template>
+ <template if="{{!serviceState.published}}">
+ <p>Before we start, you need to start the service under a name. Go to Home and publish this instance of P2B under a name like <span class="name">john-tablet</span> or <span class="name">jane-desktop</span>
+ </p>
+ </template>
+ <p>Now let's use the <span class="name">console</span> viewer. It can pretty much display anything, so it's a good one to start with</p>
+ <p>In your Linux or Mac console run:</p>
+ <pre class="code">echo "Hello World" | p2b {{publishedName}}/console</pre>
+ <p>P2B follows a basic <span class="mono">cmd | p2b google/p2b/[name]/[viewer]</span> pattern. Where <span class="mono">[name]</span> is what you publish the service under and <span class="mono">[viewer]</span> can be the name of a built-in viewer like <span class="mono">image</span> or <span class="mono">console</span> or a Url to a remote viewer that is a P2B plug-in.</p>
+ <h3>Built-in Viewers</h3>
+ <p>In addition to the basic <span class="name">console</span> viewer, P2B is preloaded with the following viewers</p>
+
+ <h4>Image</h4>
+ <p><span class="name">image</span> can display most types of images.</p>
+ <pre class="code">cat grumpy-cat.jpg | p2b {{publishedName}}/image</pre>
+
+ <h4>Git Status</h4>
+ <p>Ever wanted to sort, search and filter result of <span class="mono">git status</span> to make sense of it all? <span class="name">git/status</span> can do that. You need to use <span class="mono">git status --short</span> though, so we can parse it.</p>
+ <pre class="code">git status --short | p2b {{publishedName}}/git/status</pre>
+
+ <h4>Veyron Log Viewer</h4>
+ <span class="name">vlog</span> displays Veyron logs in a DataGrid and supports sorting, searching, paging, pausing and filtering based on time and log level. DataGrid is responsive and may hide columns on smaller screens but you can always see all the fields by using the more info icon.</p>
+ <pre class="code">cat vlogfile.txt | p2b {{publishedName}}/vlog</pre>
+ <p>If you want to pipe logs from a Veyron service directly, you need to pipe stderr or strout first using <span class="mono">2>&1</span></p>
+ <pre class="code">myVeyronServerd -v=3 2>&1 | p2b {{publishedName}}/vlog</pre>
+
+ <h4>dev/null</h4>
+ <p>No system is complete without a <span class="name">dev/null</span>. Similar to *nix <span class="mono">dev/null</span>, anything piped to it will be discarded without mercy.</p>
+ <pre class="code">cat /dev/urandom | p2b {{publishedName}}/dev/null</pre>
+
+ <h3>Remote Viewers</h3>
+ <p>In addition to built-in viewers, ad-hoc remote viewers can be hosted anywhere and used with P2B. Remote viewers are referenced by their Url without the .js extension at the end og the plug-in JavaScript file</p>
+ <pre class="code">echo "Hello World" | p2b {{publishedName}}/http://googledrive.com/host/0BzmT5cnKdCAKa3hzNEVCU2tnd3c/helloworld</pre>
+ <p>Writing remote viewers is not different than writing built-in ones and basic plug-ins are pretty straight forward to write.</p>
+ <p>At high level, plug-ins are expected to implement a <span class="mono">PipeViewer</span> interface which has a <span class="mono">play(stream)</span> method. A <span class="mono">view</span> (which is a wrapper for a DOM element) is expected to be returned from <span class="mono">play(stream)</span>. You can look at the hello world remote plug-in <a href="http://googledrive.com/host/0BzmT5cnKdCAKa3hzNEVCU2tnd3c/helloworld.js" target="_blank">code on Google drive</a> to get started on writing new remote plug-ins</p>
+</template>
+<script>
+ Polymer('p2b-help', {
+ /*
+ * Dynamic binding for the state of publishing p2b service.
+ */
+ serviceState: null,
+ get publishedName() {
+ if( this.serviceState && this.serviceState.published ) {
+ return this.serviceState.fullServiceName
+ } else {
+ return 'google/p2b/[name]';
+ }
+ },
+
+ });
+ </script>
+</polymer-element>
diff --git a/examples/pipetobrowser/browser/views/help/view.js b/examples/pipetobrowser/browser/views/help/view.js
new file mode 100644
index 0000000..3ca0592
--- /dev/null
+++ b/examples/pipetobrowser/browser/views/help/view.js
@@ -0,0 +1,15 @@
+import { exists } from 'libs/utils/exists'
+import { View } from 'libs/mvc/view'
+
+/*
+ * View representing the help page
+ * @class
+ * @extends {View}
+ */
+export class HelpView extends View {
+ constructor(serviceState) {
+ var el = document.createElement('p2b-help');
+ el.serviceState = serviceState;
+ super(el);
+ }
+}
\ No newline at end of file
diff --git a/examples/pipetobrowser/browser/views/loading/component.css b/examples/pipetobrowser/browser/views/loading/component.css
new file mode 100644
index 0000000..4411080
--- /dev/null
+++ b/examples/pipetobrowser/browser/views/loading/component.css
@@ -0,0 +1,3 @@
+.spinner {
+ margin: 1em;
+}
\ No newline at end of file
diff --git a/examples/pipetobrowser/browser/views/loading/component.html b/examples/pipetobrowser/browser/views/loading/component.html
index 2017642..0483301 100644
--- a/examples/pipetobrowser/browser/views/loading/component.html
+++ b/examples/pipetobrowser/browser/views/loading/component.html
@@ -2,7 +2,8 @@
<polymer-element name="p2b-loading">
<template>
- <div>Loading...</div>
+ <link rel="stylesheet" href="component.css">
+ <img class="spinner" src="/libs/ui-components/common/spinner.gif" alt="Loading"/>
</template>
<script>
Polymer('p2b-loading', {
diff --git a/examples/pipetobrowser/browser/views/publish/component.html b/examples/pipetobrowser/browser/views/publish/component.html
index e32d8dd..d17b40a 100644
--- a/examples/pipetobrowser/browser/views/publish/component.html
+++ b/examples/pipetobrowser/browser/views/publish/component.html
@@ -7,7 +7,7 @@
<template id="template">
<link rel="stylesheet" href="../common/common.css">
<link rel="stylesheet" href="component.css">
- <paper-input id="publishNameInput" label="Name to publish under (e.g. JohnTablet)" error="You must pick a name!" floatinglabel/></paper-input>
+ <paper-input id="publishNameInput" label="Name to publish under (e.g. john-tablet)" error="You must pick a name!" floatinglabel/></paper-input>
<paper-button class="paper colored" inkColor="#3367d6" on-click="{{ publishAction }}">Publish</paper-button>
</template>
<script>
@@ -19,7 +19,7 @@
* @event
*/
publishAction: function() {
- var name = this.$.publishNameInput.value;
+ var name = this.$.publishNameInput.value.trim();
if(name === "") {
this.$.publishNameInput.invalid = true;
this.$.publishNameInput.classList.toggle('invalid', true);