Host details

This commit is contained in:
Vincent Fiduccia 2017-02-24 02:21:15 -07:00
parent b3febc111e
commit 9900c56da0
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
18 changed files with 126 additions and 88 deletions

View File

@ -15,6 +15,13 @@ export default Ember.Component.extend({
primaryAction : Ember.computed.alias('model.primaryAction'),
sizeClass: function() {
let size = this.get('size');
if ( size && size !== 'md' ) {
return 'btn-'+size;
}
}.property('size'),
click(e) {
var tgt = Ember.$(e.target);
var more = tgt.closest('.more-actions');

View File

@ -1,11 +1,12 @@
{{yield}}
{{#if (and showPrimary model.primaryAction)}}
<button class="btn bg-default btn-{{size}}" data-primary="0" aria-label="{{t model.primaryAction.label}}">
<button class="btn bg-default {{sizeClass}}" data-primary="0" aria-label="{{t model.primaryAction.label}}">
{{#tooltip-element type="tooltip-basic" model=model.primaryAction tooltipFor="actionMenu"}}
<i class="icon-fw {{model.primaryAction.icon}}"></i>
{{/tooltip-element}}
</button>
{{/if}}
<button aria-label="{{t 'generic.moreActions'}}" aria-controls="resource-actions" class="btn bg-default btn-{{size}} more-actions" data-toggle="dropdown" data-target=".resource-actions" aria-expanded="false">
<button aria-label="{{t 'generic.moreActions'}}" aria-controls="resource-actions" class="btn {{sizeClass}} more-actions {{if showLabel 'pr-10 bg-primary' 'bg-default'}}" data-toggle="dropdown" data-target=".resource-actions" aria-expanded="false">
{{#if showLabel}}{{t 'generic.actions'}} {{/if}}
<i class="icon icon-fw icon-vertical-ellipsis" alt="{{t 'generic.moreActions'}}"></i>
</button>

View File

@ -1,6 +1,6 @@
import Ember from 'ember';
export default Ember.Component.extend({
classNames: ['header-state','section'],
classNames: ['header-state','btn'],
classNameBindings: ['model.stateColor'],
});

View File

@ -1,7 +1,2 @@
<i class="icon {{model.stateIcon}}"></i>
{{model.displayState~}}
{{#if model.showTransitioningMessage}}
<small class="force-wrap">
({{model.transitioningMessage}})
</small>
{{/if}}

View File

@ -10,13 +10,13 @@
<td data-title="{{dt.docker}}">
{{model.dockerEngineVersion}}
</td>
<td data-title="{{dt.good}}" class="text-right text-success">
<td data-title="{{dt.good}}" class="text-success">
{{model.instanceGoodCount}}
</td>
<td data-title="{{dt.other}}" class="text-right {{if model.instanceOtherCount 'text-warning text-bold' 'text-muted'}}">
<td data-title="{{dt.other}}" class="{{if model.instanceOtherCount 'text-warning text-bold' 'text-muted'}}">
{{model.instanceOtherCount}}
</td>
<td data-title="{{dt.bad}}" class="text-right {{if model.instanceBadCount 'text-error text-bold' 'text-muted'}}">
<td data-title="{{dt.bad}}" class="{{if model.instanceBadCount 'text-error text-bold' 'text-muted'}}">
{{model.instanceBadCount}}
</td>
<td data-title="{{dt.actions}}" class="actions">

View File

@ -20,7 +20,7 @@ export default Ember.Component.extend(Sortable, StickyHeader, {
search: true,
paging: true,
bulkActionsList: null,
subRows: false,
subRows: false,
availableActions: null,
selectedNodes: null,
@ -223,18 +223,33 @@ export default Ember.Component.extend(Sortable, StickyHeader, {
// ------
rowClick(e) {
let tagName = e.target.tagName;
if ( tagName === 'A' || $(e.target).data('ember-action') ) {
return;
}
let content = this.get('pagedContent');
let selection = this.get('selectedNodes');
let isCheckbox = tagName === 'INPUT' || Ember.$(e.target).hasClass('select-for-action');
let nodeId = Ember.$(e.currentTarget).find('input[type="checkbox"]').attr('nodeid');
let node = content.findBy('id', nodeId);
let tgtRow = Ember.$(e.currentTarget);
while ( tgtRow && !tgtRow.hasClass('main-row') ) {
tgtRow = tgtRow.prev();
}
if ( !node || tagName === 'A' ) {
if ( !tgtRow ) {
return;
}
let nodeId = tgtRow.find('input[type="checkbox"]').attr('nodeid');
if ( !nodeId ) {
return;
}
let node = content.findBy('id', nodeId);
if ( !node ) {
return;
}
let isSelected = selection.includes(node);
let prevNode = this.get('prevNode');
// PrevNode is only valid if it's in the current content
if ( !content.includes(prevNode) ) {
@ -321,7 +336,13 @@ export default Ember.Component.extend(Sortable, StickyHeader, {
let input = Ember.$(`input[nodeid=${id}]`);
if ( input && input.length ) {
Ember.run.next(function() { input[0].checked = on; });
Ember.$(input).closest('tr').toggleClass('row-selected', on);
let tr = Ember.$(input).closest('tr');
let first = true;
while ( tr && (first || tr.hasClass('sub-row') ) ) {
tr.toggleClass('row-selected', on);
tr = tr.next();
first = false;
}
}
}
}

View File

@ -1,4 +1,4 @@
<table class="fixed grid sortable-table striped {{if bulkActions 'has-actions'}} {{if subRows 'has-subrows'}}">
<table class="fixed grid sortable-table striped {{if bulkActions 'has-actions'}} {{if subRows 'has-sub-rows'}}">
<thead>
<tr class="fixed-header-placeholder">
{{#if bulkActions}}
@ -105,7 +105,7 @@
{{/if}}
</tr>
{{#if hasBlock}}
{{yield content 'subrow' dt}}
{{yield content 'sub-row' dt}}
{{/if}}
{{else}}
{{#if hasBlock}}

View File

@ -75,6 +75,10 @@ export default Ember.Component.extend({
}
Ember.run.next(() => {
if ( this.isDestoyed || this.isDestroying ) {
return;
}
this.set('tooltipModel', out);
});
}.property('prefix', 'lastValue', 'formatter'),

View File

@ -1,25 +1,42 @@
<section class="header clearfix">
<h1>{{#link-to "hosts"}}{{t 'hostsPage.hostPage.header.linkTo'}}{{/link-to}}</h1>
<div class="pull-right">
{{#action-menu model=host size="sm" classNames="ml-10 pull-right"}}
{{#link-to "containers.new" (query-params hostId=host.id) classNames="btn btn-sm bg-primary"}}{{t 'hostsPage.hostPage.addContainer.linkTo'}}{{/link-to}}
{{/action-menu}}
{{header-state model=host}}
<section class="header">
<div class="banner bg-info mt-0">
<div class="banner-message clearfix">
<p class="pull-left">{{t 'hostsPage.hostPage.header.singleBanner'}}</p>
<p class="pull-right">
<a href="{{href-to "hosts"}}">{{t 'hostsPage.hostPage.header.backLink'}}</a>
</p>
</div>
</div>
<div class="clearfix">
<h1>
{{t 'hostsPage.hostPage.header.title' name=host.displayName}}
{{#ember-wormhole destinationElement=graphNode renderInPlace=(not graphExpand)}}
{{info-multi-stats model=host linkName="hostStats" single=true}}
{{/ember-wormhole}}
</h1>
{{action-menu model=host showPrimary=false showLabel=true size="md" classNames="ml-10 pull-right"}}
{{header-state model=host classNames="pull-right"}}
</div>
{{#if host.description}}
<div class="force-wrap mt-5">
{{host.description}}
</div>
{{/if}}
{{#if host.showTransitioningMessage}}
<div class="force-wrap text-right mt-5 {{host.stateColor}}">
{{host.transitioningMessage}}
</div>
{{/if}}
<div class="expanded-graph"></div>
</section>
<section>
<div class="row">
<div class="col span-3 mb-15">
{{#if host.description}}
<div>
<label>{{t 'hostsPage.hostPage.infoMultiStats.description'}} </label>
<div>{{host.description}}</div>
</div>
<hr>
{{/if}}
<div>
<label>{{t 'hostsPage.hostPage.infoMultiStats.ip'}}</label>
<div>{{copy-ip ip=host.displayIp}}</div>

View File

@ -71,7 +71,7 @@ export default Ember.Controller.extend({
searchField: 'displayState',
sort: ['stateSort','displayName'],
translationKey: 'hostsPage.index.table.state',
width: '160px'
width: '120px'
},
{
name: 'name',
@ -95,21 +95,21 @@ export default Ember.Controller.extend({
},
{
name: 'good',
sort: ['instanceGoodCount','displayName'],
sort: ['instanceGoodCount:desc','displayName'],
searchField: null,
width: '60px',
icon: 'icon icon-circle text-success',
},
{
name: 'other',
sort: ['instanceOtherCount','displayName'],
sort: ['instanceOtherCount:desc','displayName'],
searchField: null,
width: '60px',
icon: 'icon icon-circle text-warning',
},
{
name: 'bad',
sort: ['instanceBadCount','displayName'],
sort: ['instanceBadCount:desc','displayName'],
searchField: null,
width: '60px',
icon: 'icon icon-circle text-error',

View File

@ -26,31 +26,30 @@
headers=headers as |host kind|}}
{{#if (eq kind "row")}}
{{host-row model=host}}
{{else if (eq kind "subrow")}}
<tr class="hide">{{! make the alternating color match }}</tr>
<tr class="subrow text-muted">
{{else if (eq kind "sub-row")}}
<tr class="sub-row hide">{{! make the alternating color match }}</tr>
<tr class="sub-row text-muted">
<td></td>
<td colspan="{{sub headers.length 4}}" class="text-small">
<td>
<span class="host-blurb text-small" role="button" {{action "toggleExpand" host.id}}>
{{#if (array-includes expandedHosts host.id)}}
<i class="icon icon-minus-square"></i> Hide Containers
{{else}}
<i class="icon icon-plus-square"></i> Show Containers
{{/if}}
</span>
</td>
<td colspan="{{sub headers.length 1}}" class="text-small">
<span class="host-blurb"><i class="icon icon-cpu"></i> {{host.cpuBlurb}}</span>
<span class="host-blurb"><i class="icon icon-memory"></i> {{host.memoryBlurb}}</span>
<span class="host-blurb"><i class="icon icon-hdd"></i> {{host.diskBlurb}}</span>
<span class="host-blurb"><i class="icon icon-host"></i> {{host.osBlurb}}</span>
</td>
<td class="text-right" colspan="3">
<span class="host-blurb text-small" role="button" {{action "toggleExpand" host.id}}>
{{#if (array-includes expandedHosts host.id)}}
Hide Containers <i class="icon icon-minus-square"></i>
{{else}}
Show Containers <i class="icon icon-plus-square"></i>
{{/if}}
</span>
</td>
<td></td>
<//tr>
{{#if (array-includes expandedHosts host.id)}}
<tr class="hide">{{! make the alternating color match }}</tr>
<tr class="subrow">
<td colspan="{{add 1 headers.length}}" class="pl-40 pr-40">
<tr class="sub-row hide">{{! make the alternating color match }}</tr>
<tr class="sub-row">
<td colspan="{{add 1 headers.length}}" class="pl-40 pr-40">
{{#if (array-includes expandedHosts host.id)}}
{{container-table
body=host.instances
stickyHeader=false
@ -58,13 +57,13 @@
bulkActions=false
search=false
}}
</td>
</tr>
{{/if}}
{{/if}}
</td>
</tr>
{{else if (eq kind "nomatch")}}
<tr><td colspan="{{headers.length}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'hostsPage.index.table.body.noMatch'}}</td></tr>
<tr><td colspan="{{headers.length}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'hostsPage.index.table.noMatch'}}</td></tr>
{{else if (eq kind "norows")}}
<tr><td colspan="{{headers.length}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'hostsPage.index.table.body.noData'}}</td></tr>
<tr><td colspan="{{headers.length}}" class="text-center text-muted lacsso pt-20 pb-20">{{t 'hostsPage.index.table.noData'}}</td></tr>
{{/if}}
{{/sortable-table}}
{{else}}

1
app/hosts/template.hbs Normal file
View File

@ -0,0 +1 @@
{{outlet}}

View File

@ -27,7 +27,7 @@
}
}
.grid.has-actions TD.state {
.grid.has-actions > TBODY > TR > TD.state {
padding-left: 0;
.badge-state {
left: -3px;

View File

@ -25,7 +25,7 @@
.banner-message {
display: table-cell;
vertical-align: middle;
padding-left: 15px;
padding: 0 15px;
}
&.bg-primary {
@ -82,4 +82,4 @@
background-color: $error;
}
}
}
}

View File

@ -48,6 +48,16 @@ TABLE {
padding: 5px;
}
&.has-sub-rows > TBODY {
> TR.main-row > TD {
padding-bottom: 0;
}
> TR.sub-row > TD {
padding-top: 0;
}
}
&.small {
> THEAD {
> TR > TH {
@ -110,14 +120,6 @@ TABLE {
&.row-selected {
background-color: yellow;
}
&:hover {
background-color: orange;
}
&.subrow:hover {
background-color: inherit;
}
}
}
@ -137,14 +139,6 @@ TABLE {
&.row-selected {
background-color: yellow;
}
&:hover {
background-color: orange;
}
&.subrow:hover {
background-color: inherit;
}
}
.select-for-action {

View File

@ -26,15 +26,11 @@ header {
margin: 0;
display: inline-block;
vertical-align: middle;
}
& > * {
display: inline-block;
vertical-align: middle;
}
& h1 {
font-size: 21px;
margin-right: 10px;
line-height: 32px;
}
&.has-tabs {
padding: 0;
ul {

View File

@ -55,6 +55,7 @@
"ember-rl-dropdown": "^0.8.0",
"ember-route-action-helper": "^2.0.0",
"ember-truth-helpers": "1.2.0",
"ember-wormhole": "0.5.1",
"express": "^4.8.5",
"forever-agent": "^0.6.1",
"glob": "^5.0.3",

View File

@ -666,7 +666,9 @@ hostsPage:
placeholder: e.g. host01
hostPage:
header:
linkTo: 'Host:'
singleBanner: Viewing a single Host
backLink: Back to all hosts
title: 'Host: {name}'
addContainer:
linkTo: Add Container
infoMultiStats: