diff --git a/ui/app/components/allocation-log.js b/ui/app/components/allocation-log.js
new file mode 100644
index 000000000..960f268d5
--- /dev/null
+++ b/ui/app/components/allocation-log.js
@@ -0,0 +1,84 @@
+import Ember from 'ember';
+import { logger } from 'nomad-ui/utils/classes/log';
+import { task } from 'ember-concurrency';
+
+const { Component, computed, inject, run } = Ember;
+
+export default Component.extend({
+ token: inject.service(),
+
+ classNames: ['boxed-section'],
+
+ allocation: null,
+ task: null,
+
+ didReceiveAttrs() {
+ if (this.get('allocation') && this.get('task')) {
+ this.send('toggleStream');
+ }
+ },
+
+ mode: 'stdout',
+
+ logUrl: computed('allocation.id', 'allocation.node.httpAddr', function() {
+ const address = this.get('allocation.node.httpAddr');
+ const allocation = this.get('allocation.id');
+
+ return `//${address}/v1/client/fs/logs/${allocation}`;
+ }),
+
+ logParams: computed('task', 'mode', function() {
+ return {
+ task: this.get('task'),
+ type: this.get('mode'),
+ };
+ }),
+
+ logger: logger('logUrl', 'logParams', function() {
+ const token = this.get('token');
+ return token.authorizedRequest.bind(token);
+ }),
+
+ head: task(function*() {
+ yield this.get('logger.gotoHead').perform();
+ run.scheduleOnce('afterRender', () => {
+ this.$('.cli-window').scrollTop(0);
+ });
+ }),
+
+ tail: task(function*() {
+ yield this.get('logger.gotoTail').perform();
+ run.scheduleOnce('afterRender', () => {
+ this.$('.cli-window').scrollTop(this.$('.cli-window')[0].scrollHeight);
+ });
+ }),
+
+ stream: task(function*() {
+ this.get('logger').on('tick', () => {
+ var cliWindow = this.$('.cli-window');
+ run.scheduleOnce('afterRender', () => {
+ cliWindow.scrollTop(cliWindow[0].scrollHeight);
+ });
+ });
+
+ yield this.get('logger').startStreaming();
+ this.get('logger').off('tick');
+ }),
+
+ actions: {
+ setMode(mode) {
+ this.send('stopStreaming');
+ this.set('mode', mode);
+ },
+ stopStreaming() {
+ this.get('logger').stop();
+ },
+ toggleStream() {
+ if (this.get('logger.isStreaming')) {
+ this.send('stopStreaming');
+ } else {
+ this.get('stream').perform();
+ }
+ },
+ },
+});
diff --git a/ui/app/controllers/allocations/allocation/task/logs.js b/ui/app/controllers/allocations/allocation/task/logs.js
deleted file mode 100644
index 4a9fe5085..000000000
--- a/ui/app/controllers/allocations/allocation/task/logs.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import Ember from 'ember';
-import { logger } from 'nomad-ui/utils/classes/log';
-import { task } from 'ember-concurrency';
-
-const { Controller, computed, inject, run, $ } = Ember;
-
-export default Controller.extend({
- token: inject.service(),
-
- mode: 'stdout',
-
- logger: logger('logUrl', 'logParams', function() {
- const token = this.get('token');
- return token.authorizedRequest.bind(token);
- }),
-
- allocation: computed.alias('model.allocation'),
- logUrl: computed('allocation.id', 'allocation.node.httpAddr', 'model.name', 'mode', function() {
- const address = this.get('allocation.node.httpAddr');
- const allocation = this.get('allocation.id');
-
- // return `//${address}/v1/client/fs/logs/${allocation}`;
- return `//127.0.0.1:4200/v1/client/fs/logs/${allocation}`;
- }),
-
- logParams: computed('model.name', 'mode', function() {
- return {
- task: this.get('model.name'),
- type: this.get('mode'),
- };
- }),
-
- head: task(function*() {
- yield this.get('stdout.gotoHead').perform();
- run.scheduleOnce('afterRender', () => {
- $('#logs').scrollTop(0);
- });
- }),
-
- tail: task(function*() {
- yield this.get('stdout.gotoTail').perform();
- run.scheduleOnce('afterRender', () => {
- $('#logs').scrollTop($('#logs')[0].scrollHeight);
- });
- }),
-
- stream: task(function*() {
- this.get('stdout').on('tick', () => {
- run.scheduleOnce('afterRender', () => {
- $('#logs').scrollTop($('#logs')[0].scrollHeight);
- });
- });
-
- yield this.get('stdout').startStreaming();
- this.get('stdout').off('tick');
- }),
-
- actions: {
- setMode(mode) {
- this.send('stopStreaming');
- this.set('mode', mode);
- },
- stream() {
- this.streamLog();
- },
- stopStreaming() {
- this.get('logger').stop();
- },
- },
-});
diff --git a/ui/app/styles/components.scss b/ui/app/styles/components.scss
index f6e19590b..0b4545c21 100644
--- a/ui/app/styles/components.scss
+++ b/ui/app/styles/components.scss
@@ -1,6 +1,7 @@
@import "./components/badge";
@import "./components/boxed-section";
@import "./components/breadcrumbs";
+@import "./components/cli-window";
@import "./components/ember-power-select";
@import "./components/empty-message";
@import "./components/error-container";
diff --git a/ui/app/styles/components/cli-window.scss b/ui/app/styles/components/cli-window.scss
new file mode 100644
index 000000000..e163c792f
--- /dev/null
+++ b/ui/app/styles/components/cli-window.scss
@@ -0,0 +1,12 @@
+.cli-window {
+ background: transparent;
+ color: $white;
+
+ height: 500px;
+ max-height: 500px;
+ overflow: auto;
+
+ .is-light {
+ color: $text;
+ }
+}
diff --git a/ui/app/styles/core/buttons.scss b/ui/app/styles/core/buttons.scss
index 0a0c69c62..27f2ba4a1 100644
--- a/ui/app/styles/core/buttons.scss
+++ b/ui/app/styles/core/buttons.scss
@@ -4,6 +4,7 @@ $button-box-shadow-standard: 0 2px 0 0 rgba($grey, 0.2);
font-weight: $weight-bold;
box-shadow: $button-box-shadow-standard;
border: 1px solid transparent;
+ text-decoration: none;
&:active,
&.is-active,
diff --git a/ui/app/templates/allocations/allocation/task/logs.hbs b/ui/app/templates/allocations/allocation/task/logs.hbs
index 0860ddbff..d6bb8aedb 100644
--- a/ui/app/templates/allocations/allocation/task/logs.hbs
+++ b/ui/app/templates/allocations/allocation/task/logs.hbs
@@ -10,16 +10,6 @@
{{#gutter-menu class="page-body"}}
{{partial "allocations/allocation/task/subnav"}}
Start: {{startOffset}} End: {{endOffset}}
- {{stdout.output}}
{{logger.output}}
+