diff --git a/app/components/service-log/component.js b/app/components/service-log/component.js
new file mode 100644
index 000000000..4e76a3b77
--- /dev/null
+++ b/app/components/service-log/component.js
@@ -0,0 +1,43 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ prefs: Ember.inject.service(),
+
+ stickyHeader: true,
+
+ showHost: true,
+ showStats: false,
+ showInstanceState: true,
+ pagingLabel: 'pagination.entry',
+
+ sortBy: 'name',
+
+ headers: [
+ {
+ name: 'time',
+ sort: ['createdTs:desc','id:desc'],
+ searchField: 'created',
+ translationKey: 'serviceLog.time',
+ width: 150,
+ },
+ {
+ name: 'level',
+ sort: ['level','createdTs:desc','id:desc'],
+ translationKey: 'serviceLog.level',
+ width: 100,
+ },
+ {
+ name: 'event',
+ sort: ['eventType','createdTs:desc','id:desc'],
+ searchField: 'eventType',
+ translationKey: 'serviceLog.event',
+ width: 200,
+ },
+ {
+ name: 'detail',
+ sort: ['description','createdTs:desc','id:desc'],
+ searchField: 'description',
+ translationKey: 'serviceLog.detail',
+ },
+ ],
+});
diff --git a/app/components/service-log/template.hbs b/app/components/service-log/template.hbs
new file mode 100644
index 000000000..5a93f0472
--- /dev/null
+++ b/app/components/service-log/template.hbs
@@ -0,0 +1,34 @@
+{{#sortable-table
+ classNames="grid sortable-table"
+ body=logs
+ searchText=searchText
+ sortBy=sortBy
+ bulkActions=false
+ search=true
+ fullRows=true
+ pagingLabel="pagination.event"
+ headers=headers as |sortable kind row dt|}}
+ {{#if (eq kind "row")}}
+
+
+ {{date-str row.created format="hh:mm:ss A"}}
+
+
+ {{upper-case row.level}}
+
+
+ {{row.eventType}}{{#if row.runTime}} ({{row.runTime}}){{/if}}
+
+
+ {{row.description}}
+
+
+ {{action-menu model=row}}
+
+
+ {{else if (eq kind "nomatch")}}
+ {{t 'containersPage.table.noMatch'}}
+ {{else if (eq kind "norows")}}
+ {{t 'containersPage.table.noData'}}
+ {{/if}}
+{{/sortable-table}}
diff --git a/app/scaling-groups/index/template.hbs b/app/scaling-groups/index/template.hbs
index fd08405fa..2793f13e8 100644
--- a/app/scaling-groups/index/template.hbs
+++ b/app/scaling-groups/index/template.hbs
@@ -58,8 +58,6 @@
{{else if (eq kind "nomatch")}}
{{t 'containersPage.table.noMatch'}}
- {{else if (eq kind "norows")}}
- {{t 'containersPage.table.noMatch'}}
{{/if}}
{{/sortable-table}}
{{else}}
diff --git a/app/service/template.hbs b/app/service/template.hbs
index 61e2b74d3..231b6b846 100644
--- a/app/service/template.hbs
+++ b/app/service/template.hbs
@@ -22,7 +22,7 @@
{{!todo copy pasta}}
-
+
{{#if service.launchConfig.memoryReservation}}
@@ -67,45 +67,210 @@
{{/if}}
+
{{#accordion-list as |al expandFn| }}
-
-
- {{#if (eq service.kind 'externalService')}}
- {{!-- since external services are the only ones that have externalIp/hostname it didnt make sense to give extIps its own route like other services --}}
-
-
-
- {{#if service.externalIpAddresses}}
-
{{t 'servicePage.external.externalIp'}}
-
- {{#each service.externalIpAddresses as |ip|}}
-
- {{ip}}
-
- {{/each}}
-
- {{else}}
-
{{t 'servicePage.external.externalHostname'}} {{service.hostname}}
- {{/if}}
-
-
-
- {{/if}}
+ {{#if (eq service.kind 'externalService')}}
+ {{!-- since external services are the only ones that have externalIp/hostname it didnt make sense to give extIps its own route like other services --}}
+
+
+
+ {{#if service.externalIpAddresses}}
+
{{t 'servicePage.external.externalIp'}}
+
+ {{#each service.externalIpAddresses as |ip|}}
+
+ {{ip}}
+
+ {{/each}}
+
+ {{else}}
+
{{t 'servicePage.external.externalHostname'}} {{service.hostname}}
+ {{/if}}
+
+
+
+ {{/if}}
- {{#accordion-list-item
- title=(t 'servicePage.portsTab.title')
- detail=(t 'servicePage.portsTab.detail')
- status=(t 'servicePage.portsTab.status' count=model.service.endpointsByPort.length)
- statusClass=(if model.service.endpointsByPort.length 'bg-success' 'text-muted')
- expandAll=al.expandAll
- expand=(action expandFn)
+ {{#if service.canHaveContainers}}
+ {{#accordion-list-item
+ title=(t 'servicePage.containersTab.title')
+ detail=(t 'servicePage.containersTab.detail')
+ status=(t 'servicePage.containersTab.status' count=service.instances.length)
+ statusClass=(if service.instances.length 'bg-success' 'text-muted')
+ expanded=true
+ expandAll=al.expandAll
+ expand=(action expandFn)
+ componentName='container-table'
+ as | parent |
+ }}
+ {{component parent.intent
+ body=service.instances
+ bulkActions=true
+ showHost=true
}}
- {{#if model.service.isActive}}
-
+ {{/accordion-list-item}}
+ {{/if}}
+ {{#if service.isBalancer}}
+ {{#accordion-list-item
+ title=(t 'formBalancerRules.label')
+ detail=(t 'formBalancerRules.detail')
+ status=(t 'formBalancerRules.status' count=(if rules.length rules.length 0))
+ statusClass=(if rules.length 'bg-success' 'text-muted')
+ expandAll=al.expandAll
+ expand=(action expandFn)
+ }}
+ {{#if rules.length}}
+
+
+
+ {{t 'formBalancerRules.priority.label'}}
+ {{t 'formBalancerRules.access.label'}}
+ {{t 'formBalancerRules.protocol.label'}}
+ {{t 'formBalancerRules.hostname.label'}}
+ {{t 'formBalancerRules.sourcePort.label'}}
+ {{t 'formBalancerRules.path.label'}}
+ {{t 'formBalancerRules.target'}}
+ {{t 'formBalancerRules.targetPort.label'}}
+ {{t 'formBalancerRules.backendName.label'}}
+
+
- {{#each model.service.endpointsByPort as |obj|}}
+
+ {{#each rules as |rule idx|}}
+
+
+ {{rule.priority}}
+
+
+
+ {{uc-first rule.access}}
+
+
+
+ {{upper-case rule.protocol}}
+
+
+
+ {{#if rule.canHostname}}
+ {{#if rule.hostname}}
+ {{rule.hostname}}
+ {{else}}
+ {{t 'generic.none'}}
+ {{/if}}
+ {{else}}
+ {{t 'generic.na'}}
+ {{/if}}
+
+
+
+ {{rule.sourcePort}}
+
+
+
+ {{#if rule.canPath}}
+ {{#if rule.path}}
+ {{rule.path}}
+ {{else}}
+ {{t 'generic.none'}}
+ {{/if}}
+ {{else}}
+ {{t 'generic.na'}}
+ {{/if}}
+
+
+
+ {{#if rule.selector}}
+ {{rule.selector}}
+ {{else}}
+
+ {{#if (not-eq service.stackId rule.service.stackId)~}}
+ {{rule.service.displayStack}}/
+ {{~/if~}}
+ {{~rule.service.displayName~}}
+
+ {{~/if~}}
+
+
+
+ {{rule.targetPort}}
+
+
+
+ {{#if rule.backendName}}
+ {{rule.backendName}}
+ {{else}}
+ {{t 'generic.none'}}
+ {{/if}}
+
+
+ {{/each}}
+
+
+ {{else}}
+
{{t 'formBalancerRules.noRules'}}
+ {{/if}}
+ {{/accordion-list-item}}
+
+ {{#accordion-list-item
+ title=(t 'servicePage.certsTab.title')
+ detail=(t 'servicePage.certsTab.detail')
+ status=(t 'servicePage.certsTab.status' count=(if model.service.lbConfig.certificateIds.length model.service.lbConfig.certificateIds.length 0))
+ statusClass=(if model.service.lbConfig.certificateIds.length 'bg-success' 'text-muted')
+ expandAll=al.expandAll
+ expand=(action expandFn)
+ }}
+
+
+
+
{{t 'servicePage.certsTab.additional'}}:
+ {{#if model.service.lbConfig.certificateIds.length}}
+
+ {{else}}
+
{{t 'generic.none'}}
+ {{/if}}
+
+
+ {{/accordion-list-item}}
+ {{/if}}
+
+ {{#if (and service.isReal (not service.isBalancer))}}
+ {{container/form-command
+ tagName=''
+ instance=service
+ isService=true
+ initialLabels=service.launchConfig.labels
+ editing=false
+ expandAll=al.expandAll
+ expandFn=expandFn
+ }}
+ {{/if}}
+
+ {{#if service.hasPorts}}
+ {{#accordion-list-item
+ title=(t 'servicePage.portsTab.title')
+ detail=(t 'servicePage.portsTab.detail')
+ status=(t 'servicePage.portsTab.status' count=service.endpointsByPort.length)
+ statusClass=(if service.endpointsByPort.length 'bg-success' 'text-muted')
+ expandAll=al.expandAll
+ expand=(action expandFn)
+ }}
+ {{#if service.isActive}}
+ {{#each model.service.endpointsByPort as |obj|}}
{{t 'servicePage.portsTab.table.header.port'}}
@@ -121,249 +286,44 @@
- {{else}}
-
{{t 'servicePage.portsTab.table.body.noData'}}
-
- {{/each}}
-
-
-
{{else}}
-
{{t 'servicePage.portsTab.notActive'}}
- {{/if}}
- {{/accordion-list-item}}
+
{{t 'servicePage.portsTab.table.body.noData'}}
+ {{/each}}
+ {{else}}
+
{{t 'servicePage.portsTab.notActive'}}
+ {{/if}}
+ {{/accordion-list-item}}
+ {{/if}}
- {{#accordion-list-item
- title=(t 'formBalancerRules.label')
- detail=(t 'formBalancerRules.detail')
- status=(t 'formBalancerRules.status' count=(if rules.length rules.length 0))
- statusClass=(if rules.length 'bg-success' 'text-muted')
- expandAll=al.expandAll
- expand=(action expandFn)
- }}
- {{#if rules.length}}
-
-
-
- {{t 'formBalancerRules.priority.label'}}
- {{t 'formBalancerRules.access.label'}}
- {{t 'formBalancerRules.protocol.label'}}
- {{t 'formBalancerRules.hostname.label'}}
- {{t 'formBalancerRules.sourcePort.label'}}
- {{t 'formBalancerRules.path.label'}}
- {{t 'formBalancerRules.target'}}
- {{t 'formBalancerRules.targetPort.label'}}
- {{t 'formBalancerRules.backendName.label'}}
-
-
+ {{labels-section model=service.launchConfig tagName='' expandAll=al.expandAll expandFn=expandFn}}
-
- {{#each rules as |rule idx|}}
-
-
- {{rule.priority}}
-
+ {{#accordion-list-item
+ title=(t 'servicePage.linksTab.header')
+ detail=(t 'servicePage.linksTab.detail')
+ status=(t 'servicePage.linksTab.status' count=service.consumedServicesWithNames.length)
+ statusClass=(if service.consumedServicesWithNames.length 'bg-success' 'text-muted')
+ expandAll=al.expandAll
+ expand=(action expandFn)
+ }}
+ {{t 'servicePage.linksTab.header'}}
+
+ {{#each service.consumedServicesWithNames as |link|}}
+ {{consumed-service-link link=link stackId=service.stackId}}
+ {{else}}
+ {{t 'servicePage.linksTab.noData'}}
+ {{/each}}
+
+ {{/accordion-list-item}}
-
- {{uc-first rule.access}}
-
-
-
- {{upper-case rule.protocol}}
-
-
-
- {{#if rule.canHostname}}
- {{#if rule.hostname}}
- {{rule.hostname}}
- {{else}}
- {{t 'generic.none'}}
- {{/if}}
- {{else}}
- {{t 'generic.na'}}
- {{/if}}
-
-
-
- {{rule.sourcePort}}
-
-
-
- {{#if rule.canPath}}
- {{#if rule.path}}
- {{rule.path}}
- {{else}}
- {{t 'generic.none'}}
- {{/if}}
- {{else}}
- {{t 'generic.na'}}
- {{/if}}
-
-
-
- {{#if rule.selector}}
- {{rule.selector}}
- {{else}}
-
- {{#if (not-eq service.stackId rule.service.stackId)~}}
- {{rule.service.displayStack}}/
- {{~/if~}}
- {{~rule.service.displayName~}}
-
- {{~/if~}}
-
-
-
- {{rule.targetPort}}
-
-
-
- {{#if rule.backendName}}
- {{rule.backendName}}
- {{else}}
- {{t 'generic.none'}}
- {{/if}}
-
-
- {{/each}}
-
-
- {{else}}
-
{{t 'formBalancerRules.noRules'}}
- {{/if}}
- {{/accordion-list-item}}
-
- {{#accordion-list-item
- title=(t 'servicePage.certsTab.title')
- detail=(t 'servicePage.certsTab.detail')
- status=(t 'servicePage.certsTab.status' count=(if model.service.lbConfig.certificateIds.length model.service.lbConfig.certificateIds.length 0))
- statusClass=(if model.service.lbConfig.certificateIds.length 'bg-success' 'text-muted')
- expandAll=al.expandAll
- expand=(action expandFn)
- }}
-
-
-
-
-
{{t 'servicePage.certsTab.additional'}}:
- {{#if model.service.lbConfig.certificateIds.length}}
-
- {{else}}
-
{{t 'generic.none'}}
- {{/if}}
-
-
- {{/accordion-list-item}}
-
- {{container/form-command
- tagName=''
- instance=service
- isService=true
- initialLabels=service.launchConfig.labels
- editing=false
- expandAll=al.expandAll
- expandFn=expandFn
- }}
-
- {{#accordion-list-item
- title=(t 'servicePage.containersTab.title')
- detail=(t 'servicePage.containersTab.detail')
- status=(t 'servicePage.containersTab.status' count=model.service.instances.length)
- statusClass=(if model.service.instances.length 'bg-success' 'text-muted')
- expandAll=al.expandAll
- expand=(action expandFn)
- componentName='container-table'
- as | parent |
- }}
- {{component parent.intent
- body=model.service.instances
- bulkActions=true
- showHost=true
- }}
- {{/accordion-list-item}}
-
- {{labels-section model=model.service.launchConfig tagName='' expandAll=al.expandAll expandFn=expandFn}}
-
- {{#accordion-list-item
- title=(t 'servicePage.linksTab.header')
- detail=(t 'servicePage.linksTab.detail')
- status=(t 'servicePage.linksTab.status' count=model.service.consumedServicesWithNames.length)
- statusClass=(if model.service.consumedServicesWithNames.length 'bg-success' 'text-muted')
- expandAll=al.expandAll
- expand=(action expandFn)
- }}
-
{{t 'servicePage.linksTab.header'}}
-
- {{#each model.service.consumedServicesWithNames as |link|}}
- {{consumed-service-link link=link stackId=model.service.stackId}}
- {{else}}
- {{t 'servicePage.linksTab.noData'}}
- {{/each}}
-
- {{/accordion-list-item}}
-
- {{#accordion-list-item
- title=(t 'servicePage.logTab.title')
- detail=(t 'servicePage.logTab.detail')
- status=(t 'servicePage.logTab.status' count=model.logs.arrangedContent.length)
- statusClass=(if model.logs.arrangedContent.length 'bg-success' 'text-muted')
- expandAll=al.expandAll
- expand=(action expandFn)
- }}
-
-
-
-
-
- {{#each model.logs.arrangedContent as |obj|}}
-
-
- {{date-str obj.created format="hh:mm:ss A"}}
-
-
- {{upper-case obj.level}}
-
-
- {{obj.eventType}}{{#if obj.runTime}} ({{obj.runTime}}){{/if}}
-
-
- {{obj.description}}
-
-
- {{action-menu model=obj}}
-
-
- {{else}}
-
-
- {{t 'servicePage.logTab.table.body.noData'}}
-
-
- {{/each}}
-
-
- {{/accordion-list-item}}
-
-
-
+ {{#accordion-list-item
+ title=(t 'servicePage.logTab.title')
+ detail=(t 'servicePage.logTab.detail')
+ status=(t 'servicePage.logTab.status' count=model.logs.arrangedContent.length)
+ statusClass=(if model.logs.arrangedContent.length 'bg-success' 'text-muted')
+ expandAll=al.expandAll
+ expand=(action expandFn)
+ }}
+ {{service-log logs=model.logs.arrangedContent}}
+ {{/accordion-list-item}}
{{/accordion-list}}
diff --git a/ember-cli-build.js b/ember-cli-build.js
index f61821fc6..60b53f3ef 100644
--- a/ember-cli-build.js
+++ b/ember-cli-build.js
@@ -49,6 +49,7 @@ module.exports = function(defaults) {
// These get version added to the query string so JS doesn't have to know the fingerprint
'assets/intl',
+ 'assets/images/resources',
'ui-light.css', 'ui-light.rtl.css',
'ui-dark.css', 'ui-dark.rtl.css',
'ui.css', 'ui.rtl.css',
diff --git a/translations/en-us.yaml b/translations/en-us.yaml
index f7946cfae..27dc1f845 100644
--- a/translations/en-us.yaml
+++ b/translations/en-us.yaml
@@ -1119,8 +1119,8 @@ servicePage:
noData: This Service has no ports.
notActive: Ports are only available while the service is Active.
logTab:
- title: Logs
- detail: 'These properties show the log options for this serivce.'
+ title: Service Log
+ detail: 'Recent orchestration events that have occurred for this service'
status: |
{count, plural,
=0 {No events}
@@ -3535,6 +3535,11 @@ pagination:
=0 {No Items}
=1 {{count} {count, plural, =1 {Item} other {Items}}}
other {{from} - {to} of {count} Items}}
+ entry: |
+ {pages, plural,
+ =0 {No Entries}
+ =1 {{count} {count, plural, =1 {Entry} other {Entries}}}
+ other {{from} - {to} of {count} Entries}}
host: |
{pages, plural,
=0 {No Hosts}
@@ -3656,6 +3661,14 @@ serviceLink:
sameStack: "{service}"
differentStack: "{stack}/{service}"
+serviceLog:
+ time: Time
+ level: Level
+ event: Event
+ detail: Detai
+ noMatch: No events match the current search
+ noData: No events have occurred recently
+
siteAccess:
header: Site Access
helpText: "Configure who should be allowed to log in and use {appName}."