Commit 25075d03 by Johannes Edmeier

Show total instance count in detail instance header

parent 67ae7c2d
......@@ -27,7 +27,7 @@
<url>https://github.com/codecentric/spring-boot-admin/</url>
<properties>
<revision>2.0.0-SNAPSHOT</revision>
<spring-boot.version>2.0.0.RC2</spring-boot.version>
<spring-boot.version>2.0.0.RELEASE</spring-boot.version>
<spring-cloud.version>Finchley.M7</spring-cloud.version>
<hazelcast-tests.version>3.9.2</hazelcast-tests.version>
<java.version>1.8</java.version>
......
......@@ -154,25 +154,25 @@
"integrity": "sha512-jJXUoNkmHozqlcXzNiYytcmEe3eNxn7Vh8hmnIoRi0TmT3ChQ0osuSApuIObIomnIcvqlA24FCpnamKvfZ7F5g=="
},
"@fortawesome/fontawesome-free-brands": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-brands/-/fontawesome-free-brands-5.0.7.tgz",
"integrity": "sha512-+rJGLIG+MDk4i4rEVvTCdBlPS8lj+pXz6dZwURN7I4XSrAayUYnU95pyMuRNNeA/fLJTX6cDFXFSFHF5I/1zcw==",
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-brands/-/fontawesome-free-brands-5.0.8.tgz",
"integrity": "sha512-r7qD8ZZt4ke0w1ZBHuINNIVHlSQpZOxhToF8CA2PK1TQsg2l/PsM2reTlzkNg/t1EldU4ivXW/qt6Y/uHEMMhw==",
"requires": {
"@fortawesome/fontawesome-common-types": "0.1.3"
}
},
"@fortawesome/fontawesome-free-regular": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-regular/-/fontawesome-free-regular-5.0.7.tgz",
"integrity": "sha512-JunQcUhMR32SGuKbC/Dt87ESxHEjl5dynJajc7YAOWpcGPsI9y/eyCLR60qON8owhlorVE4xtT+iYaJosc4MzQ==",
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-regular/-/fontawesome-free-regular-5.0.8.tgz",
"integrity": "sha512-FsLlHx6tKr6sE6Vy8rUEOJI39/UeLebsMGfcsLfvTfq//Y4hjRFJuK1LWpunmOTfT8oxUNvp9fuDPlxO42MEfg==",
"requires": {
"@fortawesome/fontawesome-common-types": "0.1.3"
}
},
"@fortawesome/fontawesome-free-solid": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-solid/-/fontawesome-free-solid-5.0.7.tgz",
"integrity": "sha512-eRboWGNrgW2cyl9pGpWfDSEc8KekBZWCCmL1Sad/K15JkqvWRKywzWzuiOt0c6LOTxOxnIDrCMI/QUUzfATf2Q==",
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-solid/-/fontawesome-free-solid-5.0.8.tgz",
"integrity": "sha512-c7cO2YkX+q1jprm/jMq7hzwl46uaeu1T+UF6ecOnvKIvpZbhmA3swomTDgXUXwVTnY17B9hc7XgXLKjzADFxOw==",
"requires": {
"@fortawesome/fontawesome-common-types": "0.1.3"
}
......@@ -216,9 +216,9 @@
"dev": true
},
"accepts": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
"integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
"dev": true,
"requires": {
"mime-types": "2.1.18",
......@@ -2488,12 +2488,13 @@
"dev": true
},
"css-hot-loader": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/css-hot-loader/-/css-hot-loader-1.3.7.tgz",
"integrity": "sha512-rxixf8u1v4Qx4xMXLC/YLOefyyRNvk7MgMkDq0vgCUQQJvz6z1acaH5JniDnnwlCSP4EPUy88ddGM05Z9GXzOQ==",
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/css-hot-loader/-/css-hot-loader-1.3.8.tgz",
"integrity": "sha512-bJ+FyuWlpjoKo0by6srYGMawRosSfNIZZJ7MHXlu6yfZGQz8dxH159cYzUkaaADhvKSwwBq/lLYy1SguQRT1FQ==",
"dev": true,
"requires": {
"loader-utils": "1.1.0",
"lodash": "4.17.5",
"normalize-url": "1.9.1"
}
},
......@@ -3773,7 +3774,7 @@
"integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=",
"dev": true,
"requires": {
"accepts": "1.3.4",
"accepts": "1.3.5",
"array-flatten": "1.1.1",
"body-parser": "1.18.2",
"content-disposition": "0.5.2",
......@@ -3927,9 +3928,9 @@
}
},
"file-loader": {
"version": "1.1.10",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.10.tgz",
"integrity": "sha512-dNnT4yJgUPtGDg0+m03kQ0b/PZi3Y12EnqYuRPNCsbYkBZc6j+fwVWy40jWzZjn5kIzQ4BLIxzJimbwAYlnPGw==",
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
"dev": true,
"requires": {
"loader-utils": "1.1.0",
......@@ -12440,9 +12441,9 @@
}
},
"webpack-bundle-analyzer": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.11.0.tgz",
"integrity": "sha512-GGz//de6DHqKIBN75vRPUqwTUobgYCzygS+ei/Z5wRpKYEZ+HO2e8Pd6CbQewGfofjRHoCFqL10pi2lu+/fqDg==",
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.11.1.tgz",
"integrity": "sha512-VKUVkVMc6TWVXmF1OxsBXoiRjYiDRA4XT0KqtbLMDK+891VX7FCuklYwzldND8J2upUcHHnuXYNTP+4mSFi4Kg==",
"dev": true,
"requires": {
"acorn": "5.4.1",
......
......@@ -10,9 +10,9 @@
},
"dependencies": {
"@fortawesome/fontawesome": "^1.1.4",
"@fortawesome/fontawesome-free-brands": "^5.0.7",
"@fortawesome/fontawesome-free-regular": "^5.0.7",
"@fortawesome/fontawesome-free-solid": "^5.0.7",
"@fortawesome/fontawesome-free-brands": "^5.0.8",
"@fortawesome/fontawesome-free-regular": "^5.0.8",
"@fortawesome/fontawesome-free-solid": "^5.0.8",
"@fortawesome/vue-fontawesome": "0.0.22",
"axios": "^0.18.0",
"bulma": "^0.6.2",
......@@ -49,7 +49,7 @@
"babel-preset-stage-2": "^6.24.1",
"clean-webpack-plugin": "^0.1.18",
"cross-env": "^5.1.3",
"css-hot-loader": "^1.3.7",
"css-hot-loader": "^1.3.8",
"css-loader": "^0.28.10",
"css-mqpacker": "^6.0.2",
"eslint": "^4.18.1",
......@@ -57,7 +57,7 @@
"eslint-plugin-html": "^4.0.2",
"eslint-plugin-vue": "^4.3.0",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.10",
"file-loader": "^1.1.11",
"glob": "^7.1.2",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^2.30.0",
......@@ -75,7 +75,7 @@
"vue-svg-loader": "^0.5.0",
"vue-template-compiler": "^2.5.13",
"webpack": "^3.11.0",
"webpack-bundle-analyzer": "^2.11.0"
"webpack-bundle-analyzer": "^2.11.1"
},
"browserslist": [
"> 2%",
......
......@@ -59,7 +59,12 @@ new Vue({
router,
el: '#app',
render(h) {
return h(sbaShell);
return h(sbaShell, {
props: {
applications: this.applications,
error: this.error
}
});
},
data: {
views: createViews(router),
......
......@@ -26,6 +26,10 @@ class Application {
this.name = name;
}
findInstance(instanceId) {
return this.instances.find(instance => instance.id === instanceId);
}
get isUnregisterable() {
return this.instances.findIndex(i => i.isUnregisterable) >= 0;
}
......@@ -77,4 +81,4 @@ class Application {
}
}
export default Application;
\ No newline at end of file
export default Application;
......@@ -19,6 +19,22 @@ import {Observable} from '@/utils/rxjs';
export default class {
constructor() {
this.applications = [];
this.applications.findInstance = (instanceId) => {
for (let application of this.applications) {
const instance = application.findInstance(instanceId);
if (instance) {
return instance;
}
}
return undefined;
};
this.applications.findApplicationForInstance = (instanceId) => {
return this.applications.find(application => !!application.findInstance(instanceId));
};
this.applications.indexOfApplication = (name) => {
return this.applications.findIndex(application => application.name === name);
};
this._listeners = {
added: [],
updated: [],
......@@ -26,10 +42,6 @@ export default class {
};
}
indexOf(name) {
return this.applications.findIndex(application => application.name === name);
}
addEventListener(type, listener) {
if (!(type in this._listeners)) {
this._listeners[type] = [];
......@@ -68,7 +80,7 @@ export default class {
.delay(5000)
).subscribe({
next: application => {
const idx = this.indexOf(application.name);
const idx = this.applications.indexOfApplication(application.name);
if (idx >= 0) {
const oldApplication = this.applications[idx];
if (application.instances.length > 0) {
......@@ -95,4 +107,4 @@ export default class {
}
}
}
}
\ No newline at end of file
}
......@@ -30,12 +30,19 @@
import logoOk from '@/assets/img/favicon.png';
export default {
computed: {
error() {
return this.$root.error;
props: {
applications: {
type: Array,
default: () => [],
},
error: {
type: Object,
default: null
}
},
computed: {
downCount() {
return this.$root.applications.reduce((current, next) => {
return this.applications.reduce((current, next) => {
return current + (next.instances.filter(instance => instance.statusInfo.status !== 'UP').length);
}, 0);
}
......
......@@ -67,16 +67,20 @@
import handle from './handle';
const component = {
props: {
applications: {
type: Array,
default: () => [],
},
error: {
type: Object,
default: null
}
},
components: {
applicationsList,
},
computed: {
applications() {
return this.$root.applications;
},
error() {
return this.$root.error;
},
statusGroups() {
const byStatus = _.groupBy(this.applications, application => application.status);
const list = _.transform(byStatus, (result, value, key) => {
......
......@@ -21,7 +21,9 @@
<div class="columns">
<div class="column is-narrow">
<h1 class="title" v-if="instance" v-text="instance.registration.name"/>
<h2 class="subtitle" v-if="instance" v-text="instance.id"/>
<h2 class="subtitle" v-if="instance">
Instance <strong v-text="instance.id"/> (of <span v-text="application.instances.length"/>)
</h2>
</div>
<div class="column">
<sba-status v-if="instance" :status="instance.statusInfo.status"
......@@ -44,6 +46,7 @@
</template>
<script>
import Application from '@/services/application';
import Instance from '@/services/instance';
export default {
......@@ -51,6 +54,10 @@
instance: {
type: Instance,
default: null
},
application: {
type: Application,
default: null
}
}
}
......
......@@ -16,14 +16,13 @@
<template>
<div>
<sba-instance-header :instance="instance"/>
<sba-instance-tabs :views="instanceViews" :instance="instance"/>
<sba-instance-header :instance="instance" :application="application"/>
<sba-instance-tabs :views="instanceViews" :instance="instance" :application="application"/>
<router-view v-if="instance" :instance="instance"/>
</div>
</template>
<script>
import instance from '@/services/instance'
import sbaInstanceHeader from './header';
import sbaInstanceTabs from './tabs';
......@@ -33,19 +32,26 @@
instanceId: {
type: String,
required: true
},
applications: {
type: Array,
default: () => [],
},
error: {
type: Object,
default: null
}
},
data: () => ({
instance: null
}),
computed: {
instance() {
return this.applications.findInstance(this.instanceId);
},
application() {
return this.applications.findApplicationForInstance(this.instanceId);
},
instanceViews() {
return this.$root.views.filter(view => view.name.lastIndexOf('instance/') === 0);
}
},
async created() {
const res = await instance.get(this.instanceId);
this.instance = res.data;
}
}
</script>
......@@ -23,7 +23,8 @@
<div class="instance-tabs__name"
:class="{ 'is-active' : isStuck }">
<h1 class="title is-5" v-if="instance" v-text="instance.registration.name"/>
<h1 class="subtitle is-6" v-if="instance" v-text="instance.id"/>
<h1 class="subtitle is-6" v-if="instance"><strong v-text="instance.id"/> (of <span
v-text="application.instances.length"/>)</h1>
</div>
</div>
<div class="level-right">
......@@ -50,17 +51,22 @@
</template>
<script>
import Application from '@/services/application';
import Instance from '@/services/instance';
export default {
props: {
views: {
type: Array,
default: () => []
},
instance: {
type: Instance,
default: null
},
views: {
type: Array,
default: () => []
application: {
type: Application,
default: null
}
},
data: () => ({
......
......@@ -16,8 +16,8 @@
<template>
<div id="app">
<sba-navbar :views="mainViews"/>
<router-view/>
<sba-navbar :views="mainViews" :applications="applications" :error="error"/>
<router-view :applications="applications" :error="error"/>
</div>
</template>
......@@ -25,6 +25,16 @@
import sbaNavbar from './navbar';
export default {
props: {
applications: {
type: Array,
default: () => [],
},
error: {
type: Object,
default: null
}
},
components: {sbaNavbar},
computed: {
mainViews() {
......
......@@ -33,7 +33,7 @@
<div class="navbar-start"/>
<div class="navbar-end">
<router-link class="navbar-item" v-for="view in views" :to="{name: view.name}" :key="view.name">
<component :is="view.handle"/>
<component :is="view.handle" :applications="applications" :error="error"/>
</router-link>
<div class="navbar-item">
......@@ -61,6 +61,14 @@
views: {
type: Array,
default: () => []
},
applications: {
type: Array,
default: () => [],
},
error: {
type: Object,
default: null
}
},
mounted() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment