Commit 9086e00c by Johannes Edmeier

Detect URLs in /info and render them as links

With this commit urls form the /info endpoint are deteceted and rendered as links. The downside is to make that work I had to drop the collapsible info section in the overview list and replaced it with an resizable/scrollabe <pre> section.
parent d4f521ca
......@@ -22,6 +22,10 @@
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
......
info:
version: @pom.version@
version: @project.version@
scm-url: @scm.url@
stage: test
logging:
......@@ -11,9 +12,6 @@ spring:
boot:
admin:
url: http://localhost:8080
cloud:
config:
enabled: false
endpoints:
health:
......
......@@ -2,33 +2,33 @@
<b>Error:</b> {{ error }}
</div>
<div style="display: flex; flex-wrap: wrap; justify-content: space-around;">
<sba-info-panel class="span5" panel-title="Application" raw="api/applications/{{ application.id }}/info">
<sba-info-panel class="span6" style="margin-left:0px" panel-title="Application" raw="api/applications/{{ application.id }}/info">
<table class="table">
<tr ng-repeat="(key, value) in info">
<td ng-bind="key"></td>
<td style="white-space: pre">{{ value | yaml }}</td>
<td style="white-space: pre" ng-bind-html="value | yaml | linkify:50"></td>
</tr>
</table>
</sba-info-panel>
<sba-info-panel class="span5" panel-title="Health" raw="api/applications/{{ application.id }}/health">
<sba-info-panel class="span6" style="margin-left:0px" panel-title="Health" raw="api/applications/{{ application.id }}/health">
<sba-health-status health="health"></sba-health-status>
</sba-info-panel>
<sba-info-panel class="span5" panel-title="Memory" raw="api/applications/{{ application.id }}/metrics/mem.*%7Cheap.*">
<sba-info-panel class="span6" style="margin-left:0px" panel-title="Memory" raw="api/applications/{{ application.id }}/metrics/mem.*%7Cheap.*">
<sba-memory-stats metrics=metrics></sba-memory-stats>
</sba-info-panel>
<sba-info-panel class="span5" panel-title="JVM" raw="api/applications/{{ application.id }}/metrics/systemload.*%7Cclasses.*%7Cuptime%7Cprocessors%7Cthreads.*">
<sba-info-panel class="span6" style="margin-left:0px"panel-title="JVM" raw="api/applications/{{ application.id }}/metrics/systemload.*%7Cclasses.*%7Cuptime%7Cprocessors%7Cthreads.*">
<sba-jvm-stats metrics="metrics"></sba-jvm-stats>
</sba-info-panel>
<sba-info-panel class="span5" panel-title="Garbage Collection" raw="api/applications/{{ application.id }}/metrics/gc.*">
<sba-info-panel class="span6" style="margin-left:0px" panel-title="Garbage Collection" raw="api/applications/{{ application.id }}/metrics/gc.*">
<sba-gc-stats metrics="metrics"></sba-gc-stats>
</sba-info-panel>
<sba-info-panel class="span5" panel-title="Servlet Container" raw="api/applications/{{ application.id }}/metrics/httpsessions.*" ng-show="metrics['httpsessions.active'] != null">
<sba-info-panel class="span6" style="margin-left:0px" panel-title="Servlet Container" raw="api/applications/{{ application.id }}/metrics/httpsessions.*" ng-show="metrics['httpsessions.active'] != null">
<sba-servlet-container-stats metrics="metrics"></sba-servlet-container-stats>
</sba-info-panel>
<sba-info-panel class="span5" panel-title="Datasources" raw="api/applications/{{ application.id }}/metrics/datasource.*" ng-show="hasDatasources">
<sba-info-panel class="span6" style="margin-left:0px" panel-title="Datasources" raw="api/applications/{{ application.id }}/metrics/datasource.*" ng-show="hasDatasources">
<sba-datasource-stats metrics="metrics"></sba-datasource-stats>
</sba-info-panel>
<sba-info-panel class="span5" panel-title="Caches" raw="api/applications/{{ application.id }}/metrics/cache.*" ng-show="hasCaches">
<sba-info-panel class="span6" style="margin-left:0px" panel-title="Caches" raw="api/applications/{{ application.id }}/metrics/cache.*" ng-show="hasCaches">
<sba-cache-stats metrics="metrics"></sba-cache-stats>
</sba-info-panel>
</div>
......@@ -7,7 +7,7 @@
<tr>
<th>Type</th>
<th>Expiry</th>
<th>remove</th>
<th>Action</th>
</tr>
<tr ng-repeat="(key, value) in $ctrl.activeFilters">
<td ng-if="value.name">by name ({{value.name}})</td>
......
......@@ -15,10 +15,32 @@
*/
'use strict';
var linkify = require('linkifyjs/string');
module.exports = function () {
return function (input, limit, begin) {
begin = begin || 0;
var lines = input.match(/[^\r\n]+/g);
return lines.splice(begin, limit).join('\n');
return function (input, maxLength) {
var max = maxLength || Number.MAX_VALUE;
return linkify(input, {
target: '_blank',
format: function(url, type) {
if (type === 'url' && url.length > max) {
url = url.replace(/https?:\/\//, '');
if (url.length > max) {
var last = url.lastIndexOf('/');
if (last >= 0 && (url.length - last) < max) {
var end = url.substr(last);
var first = url.lastIndexOf('/', max - 3 - end.length);
if (first < 0) {
first = max - 3 - end.length;
}
url = url.substr(0, first + 1) + '...' + end;
} else {
url = url.substr(0, max - 3) + '...';
}
}
}
return url;
}
});
};
};
......@@ -21,7 +21,8 @@ module.exports = function () {
return function (input) {
return yaml.dump(input, {
skipInvalid: true,
sort: true
sort: true,
lineWidth: Number.MAX_VALUE
});
};
};
......@@ -17,7 +17,7 @@
var angular = require('angular');
var module = angular.module('sba-applications', ['sba-core', require('angular-resource')]);
var module = angular.module('sba-applications', ['sba-core', require('angular-resource'), require('angular-sanitize')]);
global.sbaModules.push(module.name);
module.controller('applicationsCtrl', require('./controllers/applicationsCtrl.js'));
......@@ -29,7 +29,7 @@ module.service('NotificationFilters', require('./services/notificationFilters.js
module.service('ApplicationViews', require('./services/applicationViews.js'));
module.filter('yaml', require('./filters/yaml.js'));
module.filter('limitLines', require('./filters/limitLines.js'));
module.filter('linkify', require('./filters/linkify.js'));
module.component('sbaInfoPanel', require('./components/infoPanel.js'));
module.component('sbaAccordion', require('./components/accordion.js'));
......@@ -84,16 +84,8 @@ module.run(function ($rootScope, $state, $filter, Notification, Application, Mai
application.getInfo().then(function (response) {
var info = response.data;
application.version = info.version;
application.infoDetails = null;
application.infoShort = '';
delete info.version;
var infoYml = $filter('yaml')(info);
if (infoYml !== '{}\n') {
application.infoShort = $filter('limitLines')(infoYml, 3);
if (application.infoShort !== infoYml) {
application.infoDetails = $filter('limitLines')(infoYml, 32000, 3);
}
}
application.info = info;
}).finally(function () {
application.refreshing = false;
});
......
......@@ -4,12 +4,7 @@
<input placeholder="Filter" class="input-xxlarge" type="search" ng-model="searchFilter" />
</div>
<table class="table table-hover">
<col/>
<col/>
<col/>
<col/>
<col/>
<col style="width: 250px;" />
<thead>
<tr>
<th><span class="sortable" ng-class="orderByCssClass('name')" ng-click="orderBy('name')">Application</span> /
......@@ -25,11 +20,7 @@
<td>{{ application.name }} ({{ application.id }})
<br/><span class="muted">{{ application.serviceUrl || application.managementUrl || application.healthUrl }}</span></td>
<td>{{ application.version }}</td>
<td><span style="white-space: pre" ng-init="collapsed = true">{{application.infoShort}}</span>
<a class="btn btn-mini" ng-show="application.infoDetails" ng-click="collapsed = !collapsed">...</a>
<br/>
<span style="white-space: pre" ng-hide="collapsed">{{application.infoDetails}}</span>
</td>
<td><pre class="pre-scrollable" style="resize: vertical; height: 62px;" ng-bind-html="application.info | yaml | linkify:60"></pre></td>
<td><span class="status-{{application.statusInfo.status}}" title="{{application.statusInfo.timestamp | date:'dd.MM.yyyy HH:mm:ss' }}">{{ application.statusInfo.status }}</span>
<span ng-show="application.refreshing"><i class="fa fa-spinner fa-pulse fa-lg"></i></span>
</td>
......
......@@ -12,13 +12,15 @@
"dependencies": {
"angular": "^1.5.6",
"angular-resource": "^1.5.6",
"angular-sanitize": "^1.5.7",
"angular-ui-router": "^0.3.1",
"es5-shim": "^4.5.8",
"font-awesome": "^4.6.3",
"jquery": "^2.2.4",
"js-yaml": "^3.6.1",
"karma-chrome-launcher": "^1.0.1",
"karma-jasmine": "^1.0.2"
"karma-jasmine": "^1.0.2",
"linkifyjs": "^2.0.3"
},
"devDependencies": {
"clean-webpack-plugin": "^0.1.9",
......
'use strict';
var limitLines = require('../../../../modules/applications/filters/limitLines.js')();
describe('Filter: limitLines', function () {
it('test limit 1', function () {
expect(limitLines('1\n2\n3', 1)).toEqual('1');
expect(limitLines('1', 1)).toEqual('1');
});
it('test limit 99', function () {
expect(limitLines('1\n2\n3', 99)).toEqual('1\n2\n3');
});
it('test limit 1 begin 1', function () {
expect(limitLines('1\n2\n3', 1, 1)).toEqual('2');
});
});
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