Skip to content

Commit 0d1b65e

Browse files
committed
ui: Redesign - Service Detail Page (#7655)
* Create ConsulServiceInstanceList with styling and test * Implement ConsulServiceInstanceList to Service Detail page * Implement ConsulExternalSource to Services Show page header * Update services/show page object * Update the styling of CompositeRow * Refactor ConsulServiceList component and styling * Update ConsulExternalSource to say 'Registered via...' * Upgrade consul-api-double to patch 2.14.1 * Fix up tests to not use Kind in service models * Update ListCollection with clickFirstAnchor action * Add $typo-size-450 to typography base variables
1 parent 705785b commit 0d1b65e

File tree

43 files changed

+403
-291
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+403
-291
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
{{#let (if _externalSource _externalSource (service/external-source item)) as |externalSource|}}
2-
{{#if externalSource}}
3-
{{#if (has-block)}}
4-
{{yield
5-
(component 'consul-external-source' item=item _externalSource=externalSource)
6-
}}
7-
{{else}}
8-
<span data-test-external-source={{externalSource}} class="consul-external-source source-{{externalSource}}">
9-
{{#if (eq externalSource 'aws')}}
10-
<span>Synced from {{uppercase externalSource}}</span>
11-
{{else}}
12-
<span>Synced from {{capitalize externalSource}}</span>
13-
{{/if}}
14-
</span>
1+
{{#if item}}
2+
{{#let (if _externalSource _externalSource (service/external-source item)) as |externalSource|}}
3+
{{#if externalSource}}
4+
{{#if (has-block)}}
5+
{{yield
6+
(component 'consul-external-source' item=item _externalSource=externalSource)
7+
}}
8+
{{else}}
9+
<span data-test-external-source={{externalSource}} class="consul-external-source source-{{externalSource}}">
10+
{{#if (eq externalSource 'aws')}}
11+
<span>Registered via {{uppercase externalSource}}</span>
12+
{{else}}
13+
<span>Registered via {{capitalize externalSource}}</span>
14+
{{/if}}
15+
</span>
16+
{{/if}}
1517
{{/if}}
16-
{{/if}}
17-
{{/let}}
18+
{{/let}}
19+
{{/if}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{{yield}}
2+
{{#if (gt items.length 0)}}
3+
<ListCollection @cellHeight={{73}} @items={{items}} class="consul-service-instance-list" as |item index|>
4+
<a href={{href-to routeName item.Service.Service item.Node.Node (or item.Service.ID item.Service.Service)}}>
5+
{{item.Service.ID}}
6+
</a>
7+
<ul>
8+
<ConsulExternalSource @item={{item.Service}} as |ExternalSource|>
9+
<li>
10+
<ExternalSource />
11+
</li>
12+
</ConsulExternalSource>
13+
{{#with (reject-by 'ServiceID' '' item.Checks) as |checks|}}
14+
<li class={{service/instance-checks checks}}>
15+
{{checks.length}} service checks
16+
</li>
17+
{{/with}}
18+
{{#with (filter-by 'ServiceID' '' item.Checks) as |checks|}}
19+
<li class={{service/instance-checks checks}}>
20+
{{checks.length}} node checks
21+
</li>
22+
{{/with}}
23+
{{#if (get proxies item.Service.ID)}}
24+
<li class="proxy">
25+
connected with proxy
26+
</li>
27+
{{/if}}
28+
{{#if (gt item.Node.Node.length 0)}}
29+
<li class="node">
30+
<a href={{href-to 'dc.nodes.show' item.Node.Node}}>{{item.Node.Node}}</a>
31+
</li>
32+
{{/if}}
33+
<li class="address" data-test-address>
34+
{{#if (not-eq item.Service.Address '')}}
35+
{{item.Service.Address}}:{{item.Service.Port}}
36+
{{else}}
37+
{{item.Node.Address}}:{{item.Service.Port}}
38+
{{/if}}
39+
</li>
40+
{{#if (gt item.Service.Tags.length 0)}}
41+
<li>
42+
<TagList @items={{item.Service.Tags}}/>
43+
</li>
44+
{{/if}}
45+
</ul>
46+
</ListCollection>
47+
{{/if}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Component from '@ember/component';
2+
3+
export default Component.extend({
4+
tagName: '',
5+
});
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
{{yield}}
22
{{#if (gt items.length 0)}}
33
<ListCollection @cellHeight={{73}} @items={{items}} class="consul-service-list" as |item index|>
4-
<a href={{href-to routeName item.Name}}>
5-
<span class={{service/health-checks item}}></span>
6-
<span>
7-
{{item.Name}}
8-
</span>
9-
<YieldSlot @name="metadata" @params={{block-params item}}>
10-
{{yield}}
11-
</YieldSlot>
4+
<a href={{href-to routeName item.Name}} class={{service/health-checks item}}>
5+
{{item.Name}}
126
</a>
7+
<ul>
8+
<ConsulExternalSource @item={{item}} as |ExternalSource|>
9+
<li>
10+
<ExternalSource />
11+
</li>
12+
</ConsulExternalSource>
13+
{{#if (not-eq item.InstanceCount 0)}}
14+
<li>
15+
{{format-number item.InstanceCount}} {{pluralize item.InstanceCount 'Instance' without-count=true}}
16+
</li>
17+
{{/if}}
18+
{{#if (get proxies item.Name)}}
19+
<li class="proxy">
20+
connected with proxy
21+
</li>
22+
{{/if}}
23+
{{#if (gt items.Tags.length 0)}}
24+
<li>
25+
<TagList @items={{item.Tags}}/>
26+
</li>
27+
{{/if}}
28+
</ul>
1329
</ListCollection>
1430
{{/if}}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Component from '@ember/component';
2-
import Slotted from 'block-slots';
32

4-
export default Component.extend(Slotted, {
3+
export default Component.extend({
54
tagName: '',
65
});
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<EmberNativeScrollable @tagName="ul" @content-size={{_contentSize}} @scroll-left={{_scrollLeft}} @scroll-top={{_scrollTop}} @scrollChange={{action "scrollChange"}} @clientSizeChange={{action "clientSizeChange"}}>
22
<li></li>
33
{{~#each _cells as |cell|~}}
4-
<li style={{{cell.style}}}>{{yield cell.item cell.index }}</li>
4+
<li onclick={{action 'click'}} style={{{cell.style}}}>{{yield cell.item cell.index }}</li>
55
{{~/each~}}
66
</EmberNativeScrollable>

ui-v2/app/components/list-collection/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,9 @@ export default Component.extend(WithResizing, {
4545
this.updateScrollPosition();
4646
}
4747
},
48+
actions: {
49+
click: function(e) {
50+
return this.dom.clickFirstAnchor(e, 'li');
51+
},
52+
},
4853
});

ui-v2/app/controllers/dc/services/index.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ export default Controller.extend(WithEventSource, WithSearching, {
2121
}),
2222
services: computed('items.[]', function() {
2323
return this.items.filter(function(item) {
24-
return item.Kind === 'consul';
24+
return typeof item.Kind === 'undefined';
2525
});
2626
}),
2727
proxies: computed('items.[]', function() {
28-
return this.items.filter(function(item) {
29-
return item.Kind === 'connect-proxy';
30-
});
31-
}),
32-
withProxies: computed('proxies', function() {
3328
const proxies = {};
34-
this.proxies.forEach(item => {
35-
proxies[item.Name.replace('-proxy', '')] = true;
36-
});
29+
this.items
30+
.filter(function(item) {
31+
return item.Kind === 'connect-proxy';
32+
})
33+
.forEach(item => {
34+
proxies[item.Name.replace('-proxy', '')] = true;
35+
});
36+
3737
return proxies;
3838
}),
3939
});

ui-v2/app/controllers/dc/services/show/instances.js

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { get, computed } from '@ember/object';
33
import { alias } from '@ember/object/computed';
44
import { inject as service } from '@ember/service';
55
import WithSearching from 'consul-ui/mixins/with-searching';
6+
67
export default Controller.extend(WithSearching, {
78
dom: service('dom'),
89
items: alias('item.Nodes'),
@@ -23,4 +24,12 @@ export default Controller.extend(WithSearching, {
2324
.add(this.items)
2425
.search(get(this, this.searchParams.serviceInstance));
2526
}),
27+
keyedProxies: computed('proxies.[]', function() {
28+
const proxies = {};
29+
this.proxies.forEach(item => {
30+
proxies[item.ServiceProxy.DestinationServiceID] = true;
31+
});
32+
33+
return proxies;
34+
}),
2635
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { helper } from '@ember/component/helper';
2+
3+
export function healthChecks([items], hash) {
4+
let ChecksCritical = 0;
5+
let ChecksWarning = 0;
6+
let ChecksPassing = 0;
7+
8+
items.forEach(item => {
9+
switch (item.Status) {
10+
case 'critical':
11+
ChecksCritical += 1;
12+
break;
13+
case 'warning':
14+
ChecksWarning += 1;
15+
break;
16+
case 'passing':
17+
ChecksPassing += 1;
18+
break;
19+
default:
20+
break;
21+
}
22+
});
23+
24+
switch (true) {
25+
case ChecksCritical !== 0:
26+
return 'critical';
27+
case ChecksWarning !== 0:
28+
return 'warning';
29+
case ChecksPassing !== 0:
30+
return 'passing';
31+
default:
32+
return 'empty';
33+
}
34+
}
35+
36+
export default helper(healthChecks);

ui-v2/app/routes/dc/services/show.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export default Route.extend({
77
repo: service('repository/service'),
88
intentionRepo: service('repository/intention'),
99
chainRepo: service('repository/discovery-chain'),
10+
proxyRepo: service('repository/proxy'),
1011
settings: service('settings'),
1112
model: function(params, transition = {}) {
1213
const dc = this.modelFor('dc').dc.Name;
@@ -16,12 +17,11 @@ export default Route.extend({
1617
intentions: this.intentionRepo.findByService(params.name, dc, nspace),
1718
urls: this.settings.findBySlug('urls'),
1819
dc: dc,
19-
nspace: nspace,
2020
}).then(model => {
21-
return hash({
22-
chain: ['connect-proxy', 'mesh-gateway'].includes(get(model, 'item.Service.Kind'))
23-
? null
24-
: this.chainRepo.findBySlug(params.name, dc, nspace).catch(function(e) {
21+
return ['connect-proxy', 'mesh-gateway'].includes(get(model, 'item.Service.Kind'))
22+
? model
23+
: hash({
24+
chain: this.chainRepo.findBySlug(params.name, dc, nspace).catch(function(e) {
2525
const code = get(e, 'errors.firstObject.status');
2626
// Currently we are specifically catching a 500, but we return null
2727
// by default, so null for all errors.
@@ -38,8 +38,9 @@ export default Route.extend({
3838
return null;
3939
}
4040
}),
41-
...model,
42-
});
41+
proxies: this.proxyRepo.findAllBySlug(params.name, dc, nspace),
42+
...model,
43+
});
4344
});
4445
},
4546
setupController: function(controller, model) {

ui-v2/app/styles/base/typography/base-variables.scss

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ $typo-size-100: 3.5rem;
66
$typo-size-200: 1.8rem;
77
$typo-size-300: 1.3rem;
88
$typo-size-400: 1.2rem;
9+
$typo-size-450: 1.125rem;
910
$typo-size-500: 1rem;
1011
$typo-size-600: 0.875rem;
1112
$typo-size-700: 0.8125rem;

ui-v2/app/styles/components/app-view.scss

+7
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,11 @@ main {
115115
#toolbar-toggle:checked + * {
116116
display: block;
117117
}
118+
html.template-service.template-show #toolbar-toggle + * {
119+
display: block;
120+
padding: 4px;
121+
}
122+
html.template-service.template-show .actions {
123+
display: none;
124+
}
118125
}

ui-v2/app/styles/components/app-view/layout.scss

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020
%app-view-header dt {
2121
font-weight: bold;
2222
}
23+
%app-view-header .title-bar {
24+
display: flex;
25+
align-items: center;
26+
}
27+
%app-view-header .title-bar > h1 {
28+
border: 0;
29+
}
30+
%app-view-header .title-bar > span {
31+
margin-left: 8px;
32+
}
2333
/* units */
2434
%app-view {
2535
margin-top: 50px;
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
@import './layout';
22
@import './skin';
3-
%composite-row a:hover,
4-
%composite-row a:focus,
5-
%composite-row a:active {
3+
%composite-row:hover,
4+
%composite-row:focus,
5+
%composite-row:active {
66
@extend %composite-row-intent;
77
}
8-
%composite-row > a > span {
8+
%composite-row > a {
99
@extend %composite-row-header;
1010
}
11-
%composite-row > a > ul {
11+
%composite-row > ul {
1212
@extend %composite-row-detail;
1313
}

ui-v2/app/styles/components/composite-row/layout.scss

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
%composite-row a {
1+
%composite-row {
2+
cursor: pointer;
23
display: block;
34
box-sizing: border-box;
45
padding: 12px;
@@ -19,3 +20,6 @@
1920
%composite-row-detail > li:not(:first-child) {
2021
margin-left: 12px;
2122
}
23+
%composite-row-detail .node::before {
24+
margin-top: 2px;
25+
}

0 commit comments

Comments
 (0)