website: make demo full screen with instruction header

This commit is contained in:
Jack Pearkes 2015-04-22 18:48:24 -07:00
parent bab4f59889
commit d01348ad68
9 changed files with 231 additions and 206 deletions

View file

@ -7,33 +7,50 @@
</p>
<ul>
<li>- Unsealing your Vault</li>
<li>- Authorizing your requests</li>
<li>- Authorizing your requests to Vault</li>
<li>- Mounting a backend</li>
<li>- Reading, writing and deleting secrets</li>
<li>- Sealing your vault</li>
<li>- Sealing your Vault</li>
</ul>
<p>
Upon opening this terminal, a real in-memory Vault server was
initialized remotely. Any commands you send across will work, but closing this page
will end the session.
</p>
<p>
Please note that this is running in a shared
environment, so avoid setting any real secrets.
</p>
<p>
<strong>Use the command "next" to move foward</strong>. This will work throughout
the tutorial.
the tutorial, along with "previous".
</p>
</script>
<script type="text/x-handlebars" data-template-name="unseal">
<script type="text/x-handlebars" data-template-name="init">
<p>
<strong>{{model.humanName}}</strong>
Upon opening this terminal, you connected to a real in-memory Vault server.
Any commands you send across will work as with Vault normally, but closing this page
will end the session.
</p>
<p>
First, we need to unseal the Vault that has been initialized
for you below.
Please note that this is running in a shared environment, so avoid setting any real secrets.
</p>
</script>
<script type="text/x-handlebars" data-template-name="unseal">
<p>
<strong>{{model.humanName}}</strong>
</p>
<p>
Now we need to unseal the Vault that you have just initialized.
</p>
<p>
When a Vault server is started, it starts in a sealed state.
In this state, Vault is configured to know where and how to access the
physical storage, but doesn't know how to decrypt any of it.
</p>
<p>
Vault encrypts data with an encryption key. This key is also encrypted (but
not stored) and is called the "master key".
</p>
<p>
Decryting the master key requires a threshold of shards. In this example,
we use one shard to decrypt this master key, but you can use any number and
disribute shards to any number of operators.
</p>
<p>
Send the unseal key to Vault with "vault unseal &lt;key&gt;".

View file

@ -1,28 +1,27 @@
<!-- TODO Precompile ember templates -->
<script type="text/x-handlebars" data-template-name="demo">
<div class="terminal">
<span class="close-terminal" {{action "close"}}>X</span>
{{outlet}}
{{#if isLoading}}
<div class="loading-bar"></div>
{{/if}}
</div>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="demo/step">
{{#if notCleared}}
<div class="instruction-wrapper">
<div class="instruction">
{{partial model.instructionTemplate}}
</div>
{{/if}}
<div class="log">{{logs}}
</div>
<form {{action "submitText" on="submit"}}>
$ {{input value=currentText class="shell" spellcheck="false"}}
</form>
<div class="demo-terminal">
<span class="close-terminal" {{action "close"}}>X</span>
<div class="log">{{renderedLogs}}</div>
<form {{action "submitText" on="submit"}}>
{{#unless isLoading}}${{/unless}} {{input value=currentText class="shell" spellcheck="false"}}
</form>
{{#if isLoading}}
<div class="loading-bar"></div>
{{/if}}
</div>
</script>

View file

@ -1,4 +1,6 @@
Demo.ApplicationController = Ember.ObjectController.extend({
needs: ['demo'],
init: function() {
this._super.apply(this, arguments);
@ -10,17 +12,17 @@ Demo.ApplicationController = Ember.ObjectController.extend({
socket.onmessage = function(message) {
var data = JSON.parse(message.data),
controller = this.controllerFor('demo');
controller = this.get('controllers.demo');
// Add the item
if (data.stdout !== "") {
console.log("stdout", data.stout);
controller.appendLog(data.stdout);
console.log("stdout:", data.stout);
controller.appendLog(data.stdout, false);
}
if (data.stderr !== "") {
console.log("stderr", data.stderr);
controller.appendLog(data.stderr);
console.log("stderr:", data.stderr);
controller.appendLog(data.stderr, false);
}
controller.set('isLoading', false);

View file

@ -1,42 +0,0 @@
Demo.DemoCrudController = Ember.ObjectController.extend({
needs: ['demo', 'application'],
isLoading: Ember.computed.alias('controllers.demo.isLoading'),
currentText: Ember.computed.alias('controllers.demo.currentText'),
logs: Ember.computed.alias('controllers.demo.logs'),
logPrefix: Ember.computed.alias('controllers.demo.logPrefix'),
currentMarker: Ember.computed.alias('controllers.demo.currentMarker'),
notCleared: Ember.computed.alias('controllers.demo.notCleared'),
socket: Ember.computed.alias('controllers.application.socket'),
sendCommand: function() {
this.set('isLoading', true);
var demoController = this.get('controllers.demo');
var command = this.getWithDefault('currentText', '');
var log = this.get('log');
this.set('currentText', '');
demoController.logCommand(command);
demoController.appendLog(command, true);
switch(command) {
case "clear":
this.set('logs', "");
this.set('notCleared', false);
break;
default:
var data = JSON.stringify({type: "cli", data: {command: command}});
console.log("Sending: ", data);
this.get('socket').send(data);
}
},
actions: {
submitText: function() {
this.set('controllers.demo.isLoading', true);
// Send the actual request (fake for now)
this.sendCommand();
}
}
});

View file

@ -1,7 +1,28 @@
Demo.DemoController = Ember.ObjectController.extend({
actions: {
close: function() {
this.transitionTo('index');
},
}
isLoading: false,
logs: "",
appendLog: function(data, prefix) {
var newline;
if (prefix) {
data = '$ ' + data;
}
if (this.get('logs.length') === 0) {
newline = '';
} else {
newline = '\n';
}
this.set('logs', this.get('logs')+newline+data);
Ember.run.later(function() {
var element = $('.demo-overlay');
// Scroll to the bottom of the element
element.scrollTop(element[0].scrollHeight);
element.find('input.shell')[0].focus();
}, 5);
},
});

View file

@ -1,13 +1,17 @@
Demo.DemoStepController = Ember.ObjectController.extend({
needs: ['application'],
needs: ['application', 'demo'],
socket: Ember.computed.alias('controllers.application.socket'),
logs: Ember.computed.alias('controllers.demo.logs'),
isLoading: Ember.computed.alias('controllers.demo.isLoading'),
currentText: "",
commandLog: [],
logs: "",
cursor: 0,
notCleared: true,
isLoading: false,
renderedLogs: function() {
return this.get('logs');
}.property('logs.length'),
setFromHistory: function() {
var index = this.get('commandLog.length') + this.get('cursor');
@ -16,20 +20,6 @@ Demo.DemoStepController = Ember.ObjectController.extend({
this.set('currentText', previousMessage);
}.observes('cursor'),
appendLog: function(data, prefix) {
if (prefix) {
data = '$ ' + data;
}
this.set('logs', this.get('logs')+'\n'+data);
Ember.run.later(function() {
var element = $('.demo-overlay');
// Scroll to the bottom of the element
element.scrollTop(element[0].scrollHeight);
}, 5);
},
logCommand: function(command) {
var commandLog = this.get('commandLog');
@ -42,25 +32,51 @@ Demo.DemoStepController = Ember.ObjectController.extend({
submitText: function() {
// Send the actual request (fake for now)
this.sendCommand();
}
},
close: function() {
this.transitionTo('index');
},
next: function() {
var nextStepNumber = parseInt(this.get('model.id')) + 1;
this.transitionTo('demo.step', nextStepNumber);
},
previous: function() {
var prevStepNumber = parseInt(this.get('model.id')) - 1;
this.transitionTo('demo.step', prevStepNumber);
},
},
sendCommand: function() {
var demoController = this.get('controllers.demo');
var command = this.getWithDefault('currentText', '');
var log = this.get('log');
this.set('currentText', '');
demoController.logCommand(command);
demoController.appendLog(command, true);
this.logCommand(command);
this.get('controllers.demo').appendLog(command, true);
switch(command) {
case "":
break;
case "next":
case "forward":
this.set('notCleared', true);
this.send('next');
break;
case "previous":
case "back":
this.set('notCleared', true);
this.send('previous');
break;
case "clear":
this.set('logs', "");
this.set('notCleared', false);
break;
case "help":
this.set('notCleared', true);
break;
default:
this.set('isLoading', true);
var data = JSON.stringify({type: "cli", data: {command: command}});

View file

@ -1,3 +1,74 @@
Demo.DemoView = Ember.View.extend({
classNames: ['demo-overlay']
classNames: ['demo-overlay'],
click: function(ev) {
if ($(ev.target).hasClass('log')) {
// Ignore clicks on the log text
console.log("Ignore");
return;
}
var element = this.$();
// Record scoll position
var x = element.scrollX, y = element.scrollY;
// Focus
element.find('input.shell')[0].focus();
// Scroll back to where you were
element.scrollTop(x, y);
},
didInsertElement: function() {
var controller = this.get('controller'),
overlay = $('.sidebar-overlay'),
element = this.$();
overlay.addClass('active');
overlay.on('click', function() {
controller.transitionTo('index');
});
element.hide().fadeIn(300);
// Scroll to the bottom of the element
element.scrollTop(element[0].scrollHeight);
// Focus
element.find('input.shell')[0].focus();
// Hijack scrolling to only work within terminal
//
element.on('DOMMouseScroll mousewheel', function(e) {
e.preventDefault();
});
$('.demo-terminal').on('DOMMouseScroll mousewheel', function(e) {
var scrollTo = null;
if (e.type == 'mousewheel') {
scrollTo = (e.originalEvent.wheelDelta * -1);
} else if (e.type == 'DOMMouseScroll') {
scrollTo = 40 * e.originalEvent.detail;
}
if (scrollTo) {
e.preventDefault();
$(this).scrollTop(scrollTo + $(this).scrollTop());
}
});
},
willDestroyElement: function() {
// Remove overlay
$('.sidebar-overlay').removeClass('active');
var element = this.$();
element.fadeOut(400);
// Allow scrolling
$('body').unbind('DOMMouseScroll mousewheel');
},
});

View file

@ -1,77 +1,4 @@
Demo.DemoStepView = Ember.View.extend({
didInsertElement: function() {
var controller = this.get('controller'),
overlay = $('.sidebar-overlay'),
element = this.$();
overlay.addClass('active');
overlay.on('click', function() {
controller.transitionTo('index');
});
element.hide().fadeIn(300);
// Scroll to the bottom of the element
element.scrollTop(element[0].scrollHeight);
// Focus
element.find('input.shell')[0].focus();
// Hijack scrolling to only work within terminal
//
$(element).on('DOMMouseScroll mousewheel', function(ev) {
var scrolledEl = $(this),
scrollTop = this.scrollTop,
scrollHeight = this.scrollHeight,
height = scrolledEl.height(),
delta = (ev.type == 'DOMMouseScroll' ?
ev.originalEvent.detail * -40 :
ev.originalEvent.wheelDelta),
up = delta > 0;
var prevent = function() {
ev.stopPropagation();
ev.preventDefault();
ev.returnValue = false;
return false;
};
if (!up && -delta > scrollHeight - height - scrollTop) {
// Scrolling down, but this will take us past the bottom.
scrolledEl.scrollTop(scrollHeight);
return prevent();
} else if (up && delta > scrollTop) {
// Scrolling up, but this will take us past the top.
scrolledEl.scrollTop(0);
return prevent();
}
});
},
willDestroyElement: function() {
// Remove overlay
$('.sidebar-overlay').removeClass('active');
var element = this.$();
element.fadeOut(400);
// Allow scrolling
$('body').unbind('DOMMouseScroll mousewheel');
},
// click: function() {
// var element = this.$();
// // Record scoll position
// var x = element.scrollX, y = element.scrollY;
// // Focus
// element.find('input.shell')[0].focus();
// // Scroll back to where you were
// element.scrollTo(x, y);
// },
keyDown: function(ev) {
var cursor = this.get('controller.cursor'),
currentLength = this.get('controller.commandLog.length');
@ -115,14 +42,14 @@ Demo.DemoStepView = Ember.View.extend({
// defocus while loading
if (this.get('controller.isLoading')) {
element.blur()
element.blur();
}
}.observes('controller.isLoading'),
focus: function() {
var element = this.$().find('input.shell');
element.focus()
element.focus();
}.observes('controller.cursor'),
submitted: function() {

View file

@ -1,23 +1,52 @@
.demo-overlay {
z-index: 100;
z-index: 1000;
bottom: 0;
left: 0;
width: 100%;
height: 80%;
max-height: 80%;
height: 100%;
max-height: 100%;
line-height: 1.3;
position: fixed;
background-color: black;
color: #DDDDDD;
overflow: scroll;
display: block;
font-size: 15px;
font-family: 'Ubuntu Mono', 'Monaco', monospace;
@include box-shadow(0px -2px 30px 0px rgba(0, 0, 0, 0.40));
}
.terminal {
padding: 0px 65px 0 25px;
.instruction {
overflow: scroll;
margin: 20px;
width: 100%;
padding: 4px;
background-color: darken($blue, 28%);
p:last-child {
margin-bottom: 0px;
}
ul {
padding-left: 15px;
}
li {
list-style-type: none;
}
}
.demo-terminal {
background-color: black;
padding: 25px 65px 0 25px;
padding-bottom: 50px;
width: 100%;
top: 250px;
bottom: 0;
display: block;
overflow: scroll;
position: absolute;
.close-terminal{
display: inline-block;
@ -27,7 +56,6 @@
width: 60px;
height: 60px;
color: #8B8A8F;
background-color: #202021;
text-align: center;
line-height: 60px;
font-size: 30px;
@ -42,24 +70,6 @@
}
}
ul {
padding-left: 15px;
}
li {
list-style-type: none;
}
.instruction {
margin-top: 20px;
padding: 1px;
background-color: darken($blue, 25%);
p:last-child {
margin-bottom: 0px;
}
}
.log {
white-space: pre;
}
@ -73,5 +83,9 @@
background-color: black;
border: 0;
outline: 0;
&.hidden {
opacity: 0;
}
}
}