website: use new step oriented system for interactive demo
This commit is contained in:
parent
89dd4041b1
commit
be2cfc8503
28
website/source/_ember_steps.html.erb
Normal file
28
website/source/_ember_steps.html.erb
Normal file
|
@ -0,0 +1,28 @@
|
|||
<script type="text/x-handlebars" data-template-name="welcome">
|
||||
<p>
|
||||
<strong>Welcome to the Vault interactive demo!</strong>
|
||||
</p>
|
||||
<p>
|
||||
This will cover:
|
||||
</p>
|
||||
<ul>
|
||||
<li>- Unsealing your Vault</li>
|
||||
<li>- Authorizing your requests</li>
|
||||
<li>- Mounting a backend</li>
|
||||
<li>- Reading, writing and deleting secrets</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>Type "next" to move foward</strong>. This will work throughout
|
||||
the tutorial.
|
||||
</p>
|
||||
</script>
|
|
@ -1,25 +1,21 @@
|
|||
<!-- TODO Precompile ember templates -->
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="application">
|
||||
{{outlet}}
|
||||
</script>
|
||||
|
||||
<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>
|
||||
</script>
|
||||
|
||||
<script type="text/x-handlebars" data-template-name="demo/crud">
|
||||
<script type="text/x-handlebars" data-template-name="demo/step">
|
||||
{{#if notCleared}}
|
||||
<div class="welcome">
|
||||
Any Vault command you run passes through remotely to
|
||||
the real Vault interface, so feel free to explore, but
|
||||
be careful of the values you set.
|
||||
<div class="instruction">
|
||||
{{partial model.instructionTemplate}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//= require jquery.waypoints.min
|
||||
//= require lib/ember-template-compiler
|
||||
//= require lib/ember-1-10.min
|
||||
//= require lib/ember-data-1-0.min
|
||||
|
||||
//= require lib/String.substitute
|
||||
//= require lib/Function.prototype.bind
|
||||
|
|
|
@ -1,21 +1,25 @@
|
|||
Demo.DemoRoute = Ember.Route.extend({
|
||||
activate: function() {
|
||||
Demo.ApplicationController = Ember.ObjectController.extend({
|
||||
init: function() {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// connect to the websocket once we enter the application route
|
||||
// var socket = window.io.connect('http://localhost:8080');
|
||||
var socket = new WebSocket("ws://vault-demo-server.herokuapp.com/socket");
|
||||
|
||||
this.controllerFor('application').set('socket', socket);
|
||||
this.set('socket', socket);
|
||||
|
||||
socket.onmessage = function(message) {
|
||||
var data = JSON.parse(message.data),
|
||||
controller = this.controllerFor('demo');
|
||||
|
||||
// Add the item
|
||||
if (data.stdout) {
|
||||
if (data.stdout !== "") {
|
||||
console.log("stdout", data.stout);
|
||||
controller.appendLog(data.stdout);
|
||||
}
|
||||
|
||||
if (data.stderr) {
|
||||
if (data.stderr !== "") {
|
||||
console.log("stderr", data.stderr);
|
||||
controller.appendLog(data.stderr);
|
||||
}
|
||||
|
|
@ -1,34 +1,4 @@
|
|||
Demo.DemoController = Ember.ObjectController.extend({
|
||||
currentText: "vault help",
|
||||
commandLog: [],
|
||||
logs: "",
|
||||
cursor: 0,
|
||||
notCleared: true,
|
||||
isLoading: false,
|
||||
|
||||
setFromHistory: function() {
|
||||
var index = this.get('commandLog.length') + this.get('cursor');
|
||||
var previousMessage = this.get('commandLog')[index];
|
||||
|
||||
this.set('currentText', previousMessage);
|
||||
}.observes('cursor'),
|
||||
|
||||
appendLog: function(data, prefix) {
|
||||
if (prefix) {
|
||||
data = '$ ' + data;
|
||||
}
|
||||
|
||||
this.set('logs', this.get('logs')+'\n'+data);
|
||||
},
|
||||
|
||||
logCommand: function(command) {
|
||||
var commandLog = this.get('commandLog');
|
||||
|
||||
commandLog.push(command);
|
||||
|
||||
this.set('commandLog', commandLog);
|
||||
},
|
||||
|
||||
actions: {
|
||||
close: function() {
|
||||
this.transitionTo('index');
|
||||
|
|
70
website/source/assets/javascripts/demo/controllers/step.js
Normal file
70
website/source/assets/javascripts/demo/controllers/step.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
Demo.DemoStepController = Ember.ObjectController.extend({
|
||||
needs: ['application'],
|
||||
socket: Ember.computed.alias('controllers.application.socket'),
|
||||
|
||||
currentText: "",
|
||||
commandLog: [],
|
||||
logs: "",
|
||||
cursor: 0,
|
||||
notCleared: true,
|
||||
isLoading: false,
|
||||
|
||||
setFromHistory: function() {
|
||||
var index = this.get('commandLog.length') + this.get('cursor');
|
||||
var previousMessage = this.get('commandLog')[index];
|
||||
|
||||
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');
|
||||
|
||||
commandLog.push(command);
|
||||
|
||||
this.set('commandLog', commandLog);
|
||||
},
|
||||
|
||||
actions: {
|
||||
submitText: function() {
|
||||
// Send the actual request (fake for now)
|
||||
this.sendCommand();
|
||||
}
|
||||
},
|
||||
|
||||
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);
|
||||
|
||||
switch(command) {
|
||||
case "":
|
||||
break;
|
||||
case "clear":
|
||||
this.set('logs', "");
|
||||
this.set('notCleared', false);
|
||||
break;
|
||||
default:
|
||||
this.set('isLoading', true);
|
||||
var data = JSON.stringify({type: "cli", data: {command: command}});
|
||||
this.get('socket').send(data);
|
||||
}
|
||||
},
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
Ember.Application.initializer({
|
||||
name: 'load-steps',
|
||||
after: 'store',
|
||||
|
||||
initialize: function(container, application) {
|
||||
var store = container.lookup('store:main');
|
||||
var steps = {
|
||||
"steps": [
|
||||
{ id: 0, name: 'welcome', humanName: "Welcome to the Vault Interactive Demo!"},
|
||||
{ id: 1, name: 'unseal', humanName: "Step 1: Unsealing your Vault"},
|
||||
]
|
||||
};
|
||||
|
||||
application.register('model:step', Demo.Step);
|
||||
|
||||
store.pushPayload('step', steps);
|
||||
},
|
||||
});
|
6
website/source/assets/javascripts/demo/model/step.js
Normal file
6
website/source/assets/javascripts/demo/model/step.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
Demo.Step = DS.Model.extend({
|
||||
name: DS.attr('string'),
|
||||
humanName: DS.attr('string'),
|
||||
|
||||
instructionTemplate: Ember.computed.alias('name')
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
Demo.Router.map(function() {
|
||||
this.route('demo', { path: '/demo' }, function() {
|
||||
this.route('crud', { path: '/crud' });
|
||||
this.route('demo', function() {
|
||||
this.route('step', { path: '/:id' });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
Demo.DemoCrudRoute = Ember.Route.extend({
|
||||
});
|
18
website/source/assets/javascripts/demo/routes/step.js
Normal file
18
website/source/assets/javascripts/demo/routes/step.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
Demo.DemoStepRoute = Ember.Route.extend({
|
||||
model: function(params) {
|
||||
return this.store.find('step', params.id);
|
||||
}
|
||||
// socket: function() {
|
||||
// return this.controllerFor('application').get('socket');
|
||||
// }.property(),
|
||||
|
||||
// activate: function() {
|
||||
// var data = JSON.stringify({type: "cli", data: {command: "vault init -key-shares=1 -key-threshold=1"}});
|
||||
// var socket = this.get('socket');
|
||||
|
||||
// socket.onopen = function() {
|
||||
// console.log("ws open");
|
||||
// socket.send(data);
|
||||
// };
|
||||
// },
|
||||
});
|
|
@ -1,142 +1,3 @@
|
|||
Demo.DemoView = Ember.View.extend({
|
||||
classNames: ['demo-overlay'],
|
||||
|
||||
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');
|
||||
|
||||
switch(ev.keyCode) {
|
||||
// Down arrow
|
||||
case 40:
|
||||
if (cursor === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.incrementProperty('controller.cursor');
|
||||
break;
|
||||
|
||||
// Up arrow
|
||||
case 38:
|
||||
if ((currentLength + cursor) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.decrementProperty('controller.cursor');
|
||||
break;
|
||||
|
||||
// command + k
|
||||
case 75:
|
||||
if (ev.metaKey) {
|
||||
this.set('controller.logs', '');
|
||||
this.set('controller.notCleared', false);
|
||||
}
|
||||
break;
|
||||
|
||||
// escape
|
||||
case 27:
|
||||
this.get('controller').transitionTo('index');
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
deFocus: function() {
|
||||
var element = this.$().find('input.shell');
|
||||
|
||||
// defocus while loading
|
||||
if (this.get('controller.isLoading')) {
|
||||
element.blur()
|
||||
}
|
||||
|
||||
}.observes('controller.isLoading'),
|
||||
|
||||
focus: function() {
|
||||
var element = this.$().find('input.shell');
|
||||
element.focus()
|
||||
}.observes('controller.cursor'),
|
||||
|
||||
submitted: function() {
|
||||
var element = this.$();
|
||||
|
||||
console.log("submitted");
|
||||
|
||||
// Focus the input
|
||||
element.find('input.shell')[0].focus();
|
||||
|
||||
// Scroll to the bottom of the element
|
||||
element.scrollTop(element[0].scrollHeight);
|
||||
|
||||
}.observes('controller.logs.length')
|
||||
classNames: ['demo-overlay']
|
||||
});
|
||||
|
|
140
website/source/assets/javascripts/demo/views/step.js
Normal file
140
website/source/assets/javascripts/demo/views/step.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
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');
|
||||
|
||||
switch(ev.keyCode) {
|
||||
// Down arrow
|
||||
case 40:
|
||||
if (cursor === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.incrementProperty('controller.cursor');
|
||||
break;
|
||||
|
||||
// Up arrow
|
||||
case 38:
|
||||
if ((currentLength + cursor) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.decrementProperty('controller.cursor');
|
||||
break;
|
||||
|
||||
// command + k
|
||||
case 75:
|
||||
if (ev.metaKey) {
|
||||
this.set('controller.logs', '');
|
||||
this.set('controller.notCleared', false);
|
||||
}
|
||||
break;
|
||||
|
||||
// escape
|
||||
case 27:
|
||||
this.get('controller').transitionTo('index');
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
deFocus: function() {
|
||||
var element = this.$().find('input.shell');
|
||||
|
||||
// defocus while loading
|
||||
if (this.get('controller.isLoading')) {
|
||||
element.blur()
|
||||
}
|
||||
|
||||
}.observes('controller.isLoading'),
|
||||
|
||||
focus: function() {
|
||||
var element = this.$().find('input.shell');
|
||||
element.focus()
|
||||
}.observes('controller.cursor'),
|
||||
|
||||
submitted: function() {
|
||||
var element = this.$();
|
||||
|
||||
console.log("submitted");
|
||||
|
||||
// Focus the input
|
||||
element.find('input.shell')[0].focus();
|
||||
|
||||
// Scroll to the bottom of the element
|
||||
element.scrollTop(element[0].scrollHeight);
|
||||
|
||||
}.observes('controller.logs.length')
|
||||
});
|
4
website/source/assets/javascripts/lib/ember-data-1-0.min.js
vendored
Normal file
4
website/source/assets/javascripts/lib/ember-data-1-0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -42,8 +42,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
.welcome {
|
||||
padding-top: 20px;
|
||||
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 {
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
<%= yield %>
|
||||
|
||||
<%= partial "ember_templates" %>
|
||||
<%= partial "ember_steps" %>
|
||||
<%= partial "layouts/footer" %>
|
||||
|
||||
|
|
Loading…
Reference in a new issue