From 4b35b015169fee70ca7789eea3bba5f3382d5855 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Sat, 25 Jan 2014 13:26:43 +0100 Subject: [PATCH] display failed health checks in user interface --- .../java/sonia/scm/repository/Repository.java | 2 +- .../rest/resources/RepositoryResource.java | 7 +- scm-webapp/src/main/webapp/index.mustache | 1 + .../src/main/webapp/resources/css/style.css | 4 + .../main/webapp/resources/images/warning.png | Bin 0 -> 666 bytes .../js/repository/sonia.repository.grid.js | 37 +++++- .../sonia.repository.healthcheckfailure.js | 108 ++++++++++++++++++ 7 files changed, 152 insertions(+), 7 deletions(-) create mode 100755 scm-webapp/src/main/webapp/resources/images/warning.png create mode 100644 scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index 77e0889a69..6d0d26a72c 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -559,7 +559,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject * * @since 1.36 */ - void setHealthCheckFailures(List healthCheckFailures) + public void setHealthCheckFailures(List healthCheckFailures) { this.healthCheckFailures = healthCheckFailures; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java index 575a42c83d..54612bc32e 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java @@ -1032,6 +1032,7 @@ public class RepositoryResource repository.setProperties(null); repository.setPermissions(null); + repository.setHealthCheckFailures(null); } return repository; @@ -1118,11 +1119,11 @@ public class RepositoryResource //~--- fields --------------------------------------------------------------- /** Field description */ - private ScmConfiguration configuration; + private final ScmConfiguration configuration; /** Field description */ - private RepositoryManager repositoryManager; + private final RepositoryManager repositoryManager; /** Field description */ - private RepositoryServiceFactory servicefactory; + private final RepositoryServiceFactory servicefactory; } diff --git a/scm-webapp/src/main/webapp/index.mustache b/scm-webapp/src/main/webapp/index.mustache index b67ec3f457..e29c2cd556 100644 --- a/scm-webapp/src/main/webapp/index.mustache +++ b/scm-webapp/src/main/webapp/index.mustache @@ -131,6 +131,7 @@ + diff --git a/scm-webapp/src/main/webapp/resources/css/style.css b/scm-webapp/src/main/webapp/resources/css/style.css index dda252141a..2ce002295c 100644 --- a/scm-webapp/src/main/webapp/resources/css/style.css +++ b/scm-webapp/src/main/webapp/resources/css/style.css @@ -234,3 +234,7 @@ div.noscript-container h1 { .upload-icon { background: url('../images/add.png') no-repeat 0 0 !important; } + +.unhealthy { + color: red; +} diff --git a/scm-webapp/src/main/webapp/resources/images/warning.png b/scm-webapp/src/main/webapp/resources/images/warning.png new file mode 100755 index 0000000000000000000000000000000000000000..628cf2dae3d419ae220c8928ac71393b480745a3 GIT binary patch literal 666 zcmV;L0%iS)P)eOSYYtbpBV}~vsBnU!_?2tr-P=|^T zED%wc9ezHgW@NMb!^uT_|SvCpFLJylbx zY%bpaTGI8IYXMN$9w<3j9VkA~NYOKEQXsj?6a9_hcwfU$acAhJhB)zb_w@MVUEy@S zX&I>K-R!bhu3?(6bHWIg$HEl7{9g>>&l_qdd+UYb(1~BCo9LptNq&8>!yoJ3Ui(i5 zRJ|XnYBklL!{@$-7=3mJ>P@1c=7Oc79e-V7yf+%lD2!I;Y&nXBZ>=B!5?CB>LvEx6 znI%n)qqi$#X#wKB(U7XP2P=+4{b@j#r%9-K(8UqtSDk>0UKzf*HM9yqMZ1D!$2MdZ zR=`U>0zhOH1XqN?nY@AQqB7)Fp4{v&dKXvb43hZKvnN8;Po;+jY*}~*Z|W9Q0W%{D z^T}Cc<|r(Su=1K=P5>Z4 zg`et&Va}tdzBS-G-ZcO)zCWpJvGQwrHZ`@wpM420ac@bI5~KkTFfGEM3sPWO8co4^fI6lPnA)Y{ef%@{+SnoUk0+dW+*{8WvF8}}l07*qoM6N<$g7cXs A&j0`b literal 0 HcmV?d00001 diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js index c086072f66..7e5dd6ebed 100644 --- a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.grid.js @@ -45,6 +45,7 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { unknownType: 'Unknown', archiveIcon: 'resources/images/archive.png', + warningIcon: 'resources/images/warning.png', filterRequest: null, @@ -97,6 +98,8 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { name: 'properties' },{ name: 'archived' + },{ + name: 'healthCheckFailures' }] }), sortInfo: { @@ -215,7 +218,15 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { forceFit: true, groupMode: 'value', enableGroupingMenu: false, - groupTextTpl: '{group} ({[values.rs.length]} {[values.rs.length > 1 ? "Repositories" : "Repository"]})' + groupTextTpl: '{group} ({[values.rs.length]} {[values.rs.length > 1 ? "Repositories" : "Repository"]})', + getRowClass: function(record){ + var rowClass = ''; + var healthFailures = record.get('healthCheckFailures'); + if (healthFailures && healthFailures.length > 0){ + rowClass = 'unhealthy'; + } + return rowClass; + } }) }; @@ -229,8 +240,21 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { } }, - renderTypeIcon: function(type){ - var result = ''; + renderTypeIcon: function(type, meta, record){ + var result; + if ( record ){ + var healthFailures = record.get('healthCheckFailures'); + if (healthFailures && healthFailures.length > 0){ + result = String.format(this.typeIconTemplate, this.warningIcon, type, type); + } + } + if (!result){ + result = this.getTypeIcon(type); + } + return result; + }, + + getTypeIcon: function(type){ var icon = Sonia.repository.getTypeIcon(type); if ( icon ){ var displayName = type; @@ -429,6 +453,13 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, { Ext.getCmp('repoRmButton').setDisabled(true); } + if (admin && item.healthCheckFailures && item.healthCheckFailures.length > 0){ + panels.push({ + xtype: 'repositoryHealthCheckFailurePanel', + healthCheckFailures: item.healthCheckFailures + }); + } + // call open listeners Ext.each(Sonia.repository.openListeners, function(listener){ if (Ext.isFunction(listener)){ diff --git a/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js new file mode 100644 index 0000000000..bdc0a46ded --- /dev/null +++ b/scm-webapp/src/main/webapp/resources/js/repository/sonia.repository.healthcheckfailure.js @@ -0,0 +1,108 @@ +/* * + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + +Sonia.repository.HealthCheckFailure = Ext.extend(Ext.Panel, { + + title: 'Health check', + linkTemplate: '{0}', + + initComponent: function(){ + var items = []; + + if ( this.healthCheckFailures && this.healthCheckFailures.length > 0 ){ + for (var i=0; i0){ + this.appendSpacer(items); + } + this.appendHealthCheckFailures(items,this.healthCheckFailures[i]); + } + } + + var config = { + title: this.title, + padding: 5, + bodyCssClass: 'x-panel-mc', + layout: 'table', + layoutConfig: { + columns: 2, + tableAttrs: { + style: 'width: 80%;' + } + }, + defaults: { + style: 'font-size: 12px' + }, + items: items + }; + Ext.apply(this, Ext.apply(this.initialConfig, config)); + Sonia.repository.HealthCheckFailure.superclass.initComponent.apply(this, arguments); + }, + + appendSpacer: function(items){ + items.push({ + xtype: 'box', + height: 10, + colspan: 2 + }); + }, + + appendHealthCheckFailures: function(items, hcf){ + items.push({ + xtype: 'label', + text: 'Summary:' + },{ + xtype: 'label', + text: hcf.summary + }); + if ( hcf.url ){ + items.push({ + xtype: 'label', + text: 'Url:' + },{ + xtype: 'box', + html: String.format(this.linkTemplate, hcf.url) + }); + } + if ( hcf.description ){ + items.push({ + xtype: 'label', + text: 'Description:' + },{ + xtype: 'label', + text: hcf.description + }); + } + } + +}); + +Ext.reg('repositoryHealthCheckFailurePanel', Sonia.repository.HealthCheckFailure); \ No newline at end of file