]> source.dussan.org Git - archiva.git/commitdiff
[MRM-77] preliminary reporting web interface
authorBrett Porter <brett@apache.org>
Fri, 8 Sep 2006 14:33:45 +0000 (14:33 +0000)
committerBrett Porter <brett@apache.org>
Fri, 8 Sep 2006 14:33:45 +0000 (14:33 +0000)
git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/trunk@441516 13f79535-47bb-0310-9956-ffa450edef68

archiva-reports-standard/src/main/java/org/apache/maven/archiva/reporting/DefaultReportingStore.java
archiva-reports-standard/src/main/java/org/apache/maven/archiva/reporting/ReportingDatabase.java
archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ReportsAction.java [new file with mode: 0644]
archiva-webapp/src/main/resources/xwork.xml
archiva-webapp/src/main/webapp/WEB-INF/jsp/decorators/default.jsp
archiva-webapp/src/main/webapp/WEB-INF/jsp/include/artifactDependencies.jspf
archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/reports.jsp [new file with mode: 0644]
archiva-webapp/src/main/webapp/css/maven-theme.css
archiva-webapp/src/main/webapp/css/site.css
design/white-site/src/site/xdoc/reports.xml

index d9495308f9577b83818e5a238c5a835d25c03f60..65d920506d9e992106c44a1a36a8c11cfda02943 100644 (file)
@@ -67,7 +67,7 @@ public class DefaultReportingStore
             }
             catch ( FileNotFoundException e )
             {
-                database = new ReportingDatabase();
+                database = new ReportingDatabase( repository );
             }
 
             if ( database == null )
@@ -75,7 +75,7 @@ public class DefaultReportingStore
                 getLogger().info( "Reading report database from " + file );
                 try
                 {
-                    database = new ReportingDatabase( reader.read( fileReader, false ) );
+                    database = new ReportingDatabase( reader.read( fileReader, false ), repository );
                 }
                 catch ( IOException e )
                 {
index d50f16be4fb9e47c475d0f34f477d6fd6fd222d1..823bbe7ef45fe727a82c8425ef5a36fc31547207 100644 (file)
@@ -21,6 +21,7 @@ import org.apache.maven.archiva.reporting.model.MetadataResults;
 import org.apache.maven.archiva.reporting.model.Reporting;
 import org.apache.maven.archiva.reporting.model.Result;
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
 
 import java.util.HashMap;
@@ -38,37 +39,55 @@ public class ReportingDatabase
 
     private Map metadataMap;
 
-    private int totalFailures;
+    private int numFailures;
 
-    private int totalWarnings;
+    private int numWarnings;
+
+    private ArtifactRepository repository;
 
     public ReportingDatabase()
     {
-        reporting = new Reporting();
+        this( new Reporting(), null );
     }
 
     public ReportingDatabase( Reporting reporting )
+    {
+        this( reporting, null );
+    }
+
+    public ReportingDatabase( ArtifactRepository repository )
+    {
+        this( new Reporting(), repository );
+    }
+
+    public ReportingDatabase( Reporting reporting, ArtifactRepository repository )
     {
         this.reporting = reporting;
+
+        this.repository = repository;
+
+        initArtifactMap();
+
+        initMetadataMap();
     }
 
     public void addFailure( Artifact artifact, String reason )
     {
         ArtifactResults results = getArtifactResults( artifact );
         results.addFailure( createResults( reason ) );
-        totalFailures++;
+        numFailures++;
     }
 
     public void addWarning( Artifact artifact, String reason )
     {
         ArtifactResults results = getArtifactResults( artifact );
         results.addWarning( createResults( reason ) );
-        totalWarnings++;
+        numWarnings++;
     }
 
     private ArtifactResults getArtifactResults( Artifact artifact )
     {
-        Map artifactMap = getArtifactMap();
+        Map artifactMap = this.artifactMap;
 
         String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(),
                                      artifact.getType(), artifact.getClassifier() );
@@ -89,25 +108,21 @@ public class ReportingDatabase
         return results;
     }
 
-    private Map getArtifactMap()
+    private void initArtifactMap()
     {
-        if ( artifactMap == null )
+        Map map = new HashMap();
+        for ( Iterator i = reporting.getArtifacts().iterator(); i.hasNext(); )
         {
-            Map map = new HashMap();
-            for ( Iterator i = reporting.getArtifacts().iterator(); i.hasNext(); )
-            {
-                ArtifactResults result = (ArtifactResults) i.next();
+            ArtifactResults result = (ArtifactResults) i.next();
 
-                String key = getArtifactKey( result.getGroupId(), result.getArtifactId(), result.getVersion(),
-                                             result.getType(), result.getClassifier() );
-                map.put( key, result );
+            String key = getArtifactKey( result.getGroupId(), result.getArtifactId(), result.getVersion(),
+                                         result.getType(), result.getClassifier() );
+            map.put( key, result );
 
-                totalFailures += result.getFailures().size();
-                totalWarnings += result.getWarnings().size();
-            }
-            artifactMap = map;
+            numFailures += result.getFailures().size();
+            numWarnings += result.getWarnings().size();
         }
-        return artifactMap;
+        artifactMap = map;
     }
 
     private static String getArtifactKey( String groupId, String artifactId, String version, String type,
@@ -127,35 +142,31 @@ public class ReportingDatabase
     {
         MetadataResults results = getMetadataResults( metadata, System.currentTimeMillis() );
         results.addFailure( createResults( reason ) );
-        totalFailures++;
+        numFailures++;
     }
 
     public void addWarning( RepositoryMetadata metadata, String reason )
     {
         MetadataResults results = getMetadataResults( metadata, System.currentTimeMillis() );
         results.addWarning( createResults( reason ) );
-        totalWarnings++;
+        numWarnings++;
     }
 
-    private Map getMetadataMap()
+    private void initMetadataMap()
     {
-        if ( metadataMap == null )
+        Map map = new HashMap();
+        for ( Iterator i = reporting.getMetadata().iterator(); i.hasNext(); )
         {
-            Map map = new HashMap();
-            for ( Iterator i = reporting.getMetadata().iterator(); i.hasNext(); )
-            {
-                MetadataResults result = (MetadataResults) i.next();
+            MetadataResults result = (MetadataResults) i.next();
 
-                String key = getMetadataKey( result.getGroupId(), result.getArtifactId(), result.getVersion() );
+            String key = getMetadataKey( result.getGroupId(), result.getArtifactId(), result.getVersion() );
 
-                map.put( key, result );
+            map.put( key, result );
 
-                totalFailures += result.getFailures().size();
-                totalWarnings += result.getWarnings().size();
-            }
-            metadataMap = map;
+            numFailures += result.getFailures().size();
+            numWarnings += result.getWarnings().size();
         }
-        return metadataMap;
+        metadataMap = map;
     }
 
     private static String getMetadataKey( String groupId, String artifactId, String version )
@@ -165,12 +176,12 @@ public class ReportingDatabase
 
     public int getNumFailures()
     {
-        return totalFailures;
+        return numFailures;
     }
 
     public int getNumWarnings()
     {
-        return totalWarnings;
+        return numWarnings;
     }
 
     public Reporting getReporting()
@@ -191,7 +202,7 @@ public class ReportingDatabase
     public boolean isMetadataUpToDate( RepositoryMetadata metadata, long timestamp )
     {
         String key = getMetadataKey( metadata );
-        Map map = getMetadataMap();
+        Map map = metadataMap;
         MetadataResults results = (MetadataResults) map.get( key );
         return results != null && results.getLastModified() >= timestamp;
     }
@@ -207,14 +218,18 @@ public class ReportingDatabase
         MetadataResults results = getMetadataResults( metadata, lastModified );
 
         results.setLastModified( lastModified );
+
+        numFailures -= results.getFailures().size();
         results.getFailures().clear();
+
+        numWarnings -= results.getWarnings().size();
         results.getWarnings().clear();
     }
 
     private MetadataResults getMetadataResults( RepositoryMetadata metadata, long lastModified )
     {
         String key = getMetadataKey( metadata );
-        Map metadataMap = getMetadataMap();
+        Map metadataMap = this.metadataMap;
         MetadataResults results = (MetadataResults) metadataMap.get( key );
         if ( results == null )
         {
@@ -237,7 +252,7 @@ public class ReportingDatabase
 
     public void removeArtifact( Artifact artifact )
     {
-        Map map = getArtifactMap();
+        Map map = artifactMap;
 
         String key = getArtifactKey( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(),
                                      artifact.getType(), artifact.getClassifier() );
@@ -251,7 +266,16 @@ public class ReportingDatabase
                     i.remove();
                 }
             }
+
+            numFailures -= results.getFailures().size();
+            numWarnings -= results.getWarnings().size();
+
             map.remove( key );
         }
     }
+
+    public ArtifactRepository getRepository()
+    {
+        return repository;
+    }
 }
diff --git a/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ReportsAction.java b/archiva-webapp/src/main/java/org/apache/maven/archiva/web/action/ReportsAction.java
new file mode 100644 (file)
index 0000000..0e5efac
--- /dev/null
@@ -0,0 +1,81 @@
+package org.apache.maven.archiva.web.action;
+
+/*
+ * Copyright 2005-2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.opensymphony.xwork.ActionSupport;
+import org.apache.maven.archiva.configuration.Configuration;
+import org.apache.maven.archiva.configuration.ConfigurationStore;
+import org.apache.maven.archiva.configuration.ConfiguredRepositoryFactory;
+import org.apache.maven.archiva.configuration.RepositoryConfiguration;
+import org.apache.maven.archiva.reporting.ReportingDatabase;
+import org.apache.maven.archiva.reporting.ReportingStore;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Repository reporting.
+ *
+ * @plexus.component role="com.opensymphony.xwork.Action" role-hint="reportsAction"
+ */
+public class ReportsAction
+    extends ActionSupport
+{
+    /**
+     * @plexus.requirement
+     */
+    private ReportingStore reportingStore;
+
+    /**
+     * @plexus.requirement
+     */
+    private ConfigurationStore configurationStore;
+
+    /**
+     * @plexus.requirement
+     */
+    private ConfiguredRepositoryFactory factory;
+
+    private List databases;
+
+    public String execute()
+        throws Exception
+    {
+        databases = new ArrayList();
+
+        Configuration configuration = configurationStore.getConfigurationFromStore();
+
+        for ( Iterator i = configuration.getRepositories().iterator(); i.hasNext(); )
+        {
+            RepositoryConfiguration repositoryConfiguration = (RepositoryConfiguration) i.next();
+
+            ArtifactRepository repository = factory.createRepository( repositoryConfiguration );
+
+            ReportingDatabase database = reportingStore.getReportsFromStore( repository );
+
+            databases.add( database );
+        }
+        return SUCCESS;
+    }
+
+    public List getDatabases()
+    {
+        return databases;
+    }
+}
index 382b15631440f9a4e8ef03f453119529258f33e9..61def7a32360937bde410e8097b4d3fa2f4e1c8a 100644 (file)
       <result>/WEB-INF/jsp/showArtifact.jsp</result>
     </action>
 
+    <action name="reports" class="reportsAction">
+      <result>/WEB-INF/jsp/reports/reports.jsp</result>
+    </action>
+
     <action name="showArtifactDependencies" class="showArtifactAction" method="dependencies">
       <result>/WEB-INF/jsp/showArtifact.jsp</result>
     </action>
index 20476d74468ae5da2e015593708a0e9bc66ea4b8..4ee4b35f8ab97e80acfc09112a07e92c91787710 100644 (file)
   </title>
 
   <style type="text/css" media="all">
-    @import url( "<%= request.getContextPath() %>/css/maven-base.css" );
-    @import url( "<%= request.getContextPath() %>/css/maven-theme.css" );
-    @import url( "<%= request.getContextPath() %>/css/site.css" );
+    @import url( "<c:url value="/css/maven-base.css" />" );
+    @import url( "<c:url value="/css/maven-theme.css" />" );
+    @import url( "<c:url value="/css/site.css" />" );
   </style>
-  <link rel="stylesheet" href="<%= request.getContextPath() %>/css/print.css" type="text/css" media="print"/>
+  <link rel="stylesheet" href="<c:url value="/css/print.css"/>" type="text/css" media="print"/>
   <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
 </head>
 
     <ww:url id="logoutUrl" action="logout" namespace="/"/>
     <ww:url id="registerUrl" action="register" namespace="/"/>
     <ww:if test="${sessionScope.authStatus != true}">
-      <ww:a href="%{loginUrl}">Login</ww:a> or <ww:a href="%{registerUrl}">Register</ww:a> 
+      <ww:a href="%{loginUrl}">Login</ww:a>
+      or
+      <ww:a href="%{registerUrl}">Register</ww:a>
     </ww:if>
     <ww:else>
-      Welcome, <b>${sessionScope.user.username}</b> - <ww:a href="%{logoutUrl}">Logout</ww:a>
+      Welcome, <b>${sessionScope.user.username}</b> -
+      <ww:a href="%{logoutUrl}">Logout</ww:a>
     </ww:else>
   </div>
 
     </ul>
     <h5>Manage</h5>
     <ul>
+      <li class="none">
+        <my:currentWWUrl action="reports" namespace="/">Reports</my:currentWWUrl>
+      </li>
 
       <%-- TODO
-            <li class="none">
-              <a href="#">Reports</a>
-            </li>
-
             <li class="none">
               <a href="#">Synchronisation</a>
             </li>
index c9501cca5f4c964059dacf5c1bc4ec991b16d085..32477f58a4248545f402a83d636ab84691b5cdb3 100644 (file)
@@ -1,7 +1,7 @@
 <%@ taglib prefix="ww" uri="/webwork" %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
-<%-- TODO: paginate --%>
+<%-- TODO: paginate! --%>
 <c:forEach items="${dependencies}" var="dependency">
   <h3>
     <c:set var="url">
diff --git a/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/reports.jsp b/archiva-webapp/src/main/webapp/WEB-INF/jsp/reports/reports.jsp
new file mode 100644 (file)
index 0000000..2905bea
--- /dev/null
@@ -0,0 +1,181 @@
+<%--
+  ~ Copyright 2005-2006 The Apache Software Foundation.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  --%>
+
+<%@ taglib prefix="ww" uri="/webwork" %>
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
+
+<html>
+<head>
+  <title>Repository Health</title>
+  <ww:head/>
+</head>
+
+<body>
+
+<h1>Reports</h1>
+
+<div id="contentArea">
+
+<ww:set name="databases" value="databases"/>
+<c:forEach items="${databases}" var="database">
+<h2>Repository: ${database.repository.name}</h2>
+
+<p>
+  Status:
+  <img src="<c:url value="/images/icon_error_sml.gif"/>" width="15" height="15" alt=""/>
+    ${database.numFailures}
+  <img src="<c:url value="/images/icon_warning_sml.gif"/>" width="15" height="15" alt=""/>
+    ${database.numWarnings}
+    <%-- TODO!
+          (<a href="#">Repair all</a>)
+    --%>
+</p>
+
+<%-- TODO! factor out common parts, especially artifact rendering tag --%>
+<%-- TODO! paginate --%>
+<c:if test="${!empty(database.reporting.artifacts)}">
+  <h3>Artifacts</h3>
+  <c:forEach items="${database.reporting.artifacts}" var="artifact" begin="0" end="2">
+    <ul>
+      <c:forEach items="${artifact.failures}" var="result">
+        <li class="errorBullet">${result.reason}</li>
+      </c:forEach>
+      <c:forEach items="${artifact.warnings}" var="result">
+        <li class="warningBullet">${result.reason}</li>
+      </c:forEach>
+    </ul>
+    <p style="text-indent: 3em;">
+          <span style="font-size: x-small">
+            <%-- TODO! share with browse as a tag --%>
+          <c:set var="cumulativeGroup" value=""/>
+          <c:forTokens items="${artifact.groupId}" delims="." var="part">
+            <c:choose>
+              <c:when test="${empty(cumulativeGroup)}">
+                <c:set var="cumulativeGroup" value="${part}"/>
+              </c:when>
+              <c:otherwise>
+                <c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
+              </c:otherwise>
+            </c:choose>
+            <c:set var="url">
+              <ww:url action="browseGroup" namespace="/">
+                <ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
+              </ww:url>
+            </c:set>
+            <a href="${url}">${part}</a> /
+          </c:forTokens>
+          <strong>${artifact.artifactId}</strong>
+          | <strong>Version:</strong>
+          <c:set var="url">
+            <ww:url action="showArtifact" namespace="/">
+              <ww:param name="groupId" value="%{'${artifact.groupId}'}"/>
+              <ww:param name="artifactId" value="%{'${artifact.artifactId}'}"/>
+              <c:if test="${!empty(artifact.version)}">
+                <ww:param name="version" value="%{'${artifact.version}'}"/>
+              </c:if>
+            </ww:url>
+          </c:set>
+          <a href="${url}">${artifact.version}</a>
+          <c:if test="${!empty(artifact.classifier)}">
+            | <strong>Classifier:</strong> ${artifact.classifier}
+          </c:if>
+        </span>
+    </p>
+    <%-- TODO!
+              <td>
+                <a href="#">Repair</a>
+              </td>
+    --%>
+  </c:forEach>
+  <c:if test="${fn:length(database.reporting.artifacts) gt 3}">
+    <p>
+      <b>... more ...</b>
+    </p>
+  </c:if>
+</c:if>
+<c:if test="${!empty(database.reporting.metadata)}">
+  <h3>Metadata</h3>
+  <c:forEach items="${database.reporting.metadata}" var="metadata" begin="0" end="2">
+    <ul>
+      <c:forEach items="${metadata.failures}" var="result">
+        <li class="errorBullet">${result.reason}</li>
+      </c:forEach>
+      <c:forEach items="${metadata.warnings}" var="result">
+        <li class="warningBullet">${result.reason}</li>
+      </c:forEach>
+    </ul>
+    <p style="text-indent: 3em;">
+          <span style="font-size: x-small">
+            <%-- TODO! share with browse as a tag --%>
+          <c:set var="cumulativeGroup" value=""/>
+          <c:forTokens items="${metadata.groupId}" delims="." var="part" varStatus="i">
+            <c:choose>
+              <c:when test="${empty(cumulativeGroup)}">
+                <c:set var="cumulativeGroup" value="${part}"/>
+              </c:when>
+              <c:otherwise>
+                <c:set var="cumulativeGroup" value="${cumulativeGroup}.${part}"/>
+              </c:otherwise>
+            </c:choose>
+            <c:set var="url">
+              <ww:url action="browseGroup" namespace="/">
+                <ww:param name="groupId" value="%{'${cumulativeGroup}'}"/>
+              </ww:url>
+            </c:set>
+            <a href="${url}">${part}</a>
+            <c:if test="${!i.last}">
+              /
+            </c:if>
+          </c:forTokens>
+              <c:if test="${!empty(metadata.artifactId)}">
+                <c:set var="url">
+                  <ww:url action="browseArtifact" namespace="/">
+                    <ww:param name="groupId" value="%{'${metadata.groupId}'}"/>
+                    <ww:param name="artifactId" value="%{'${metadata.artifactId}'}"/>
+                  </ww:url>
+                </c:set>
+                / <a href="${url}">${metadata.artifactId}</a>
+              </c:if>
+<c:if test="${!empty(metadata.version)}"> | <strong>Version:</strong>
+  <c:set var="url">
+    <ww:url action="showArtifact" namespace="/">
+      <ww:param name="groupId" value="%{'${metadata.groupId}'}"/>
+      <ww:param name="artifactId" value="%{'${metadata.artifactId}'}"/>
+      <ww:param name="version" value="%{'${metadata.version}'}"/>
+    </ww:url>
+  </c:set>
+  <a href="${url}">${metadata.version}</a>
+</c:if>       
+        </span>
+    </p>
+    <%-- TODO!
+              <td>
+                <a href="#">Repair</a>
+              </td>
+    --%>
+  </c:forEach>
+  <c:if test="${fn:length(database.reporting.metadata) gt 3}">
+    <p>
+      <b>... more ...</b>
+    </p>
+  </c:if>
+</c:if>
+</c:forEach>
+</div>
+
+</body>
+</html>
index b52a561b0c74084fcbf37114f8ee711e11f42d23..8f1d8fc4befe2ba7bbdc542e29543a0d44b19b37 100644 (file)
@@ -31,6 +31,7 @@ th {
     text-align: right;
     padding-right: 1em;
     font-size: x-small;
+    vertical-align: top;
 }
 
 .infoTable th {
index dff21cc7bc7e89ceed71dbfcc0b8fd626a105dcb..bb03df7830f0fd27f628af552571e65fa30b917c 100644 (file)
 .actionMessage {
     font-weight: bold;
 }
+
+.errorBullet {
+    list-style-image: url( "../images/icon_error_sml.gif" );
+}
+
+.warningBullet {
+    list-style-image: url( "../images/icon_warning_sml.gif" );
+}
index ab7b8738aca84ae506768a5223dab23aa1e7acda..7de7c34d4d96d5cf9ff6831bb12934135f20d3bd 100644 (file)
     </div>
 
     <div id="contentArea">
-      <h2>Status</h2>
+      <h2>Repository 1</h2>
+
+      <p>
+        Status:
+        <img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
+        2
+        <img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
+        0
+        (
+        <a href="#">Repair all</a>
+        )
+      </p>
+
+      <h3>Artifacts</h3>
       <table>
         <tr>
-          <th>Last run</th>
-          <td>1 February 13:01:04</td>
-        </tr>
-        <tr>
-          <th>Next run</th>
-          <td>1 February 17:00:00</td>
+          <td>
+            <img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
+          </td>
+          <td>
+            File is missing SHA1 checksum
+            <p>
+              <span style="font-size: x-small">
+                <strong>Group ID:</strong>
+                <a href="browse2.html">org</a>
+                /
+                <a href="browse2.html">apache</a>
+                /
+                <a href="browse2.html">maven</a>
+                <strong>Artifact ID:</strong>
+                <a href="browse3.html">maven-artifact</a>
+                <strong>Version(s):</strong>
+                <a href="artifact.html">2.0</a>
+              </span>
+            </p>
+          </td>
+          <td>
+            <a href="#">Repair</a>
+          </td>
         </tr>
         <tr>
-          <th>Status</th>
           <td>
-            <span class="statusWarn">WARNING</span>
-            : some warnings were found.
+            <img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
+          </td>
+          <td>File is missing SHA1 checksum
+            <p>
+              <span style="font-size: x-small">
+                <strong>Group ID:</strong>
+                <a href="browse2.html">org</a>
+                /
+                <a href="browse2.html">apache</a>
+                /
+                <a href="browse2.html">maven</a>
+                <strong>Artifact ID:</strong>
+                <a href="browse3.html">maven-artifact</a>
+                <strong>Version(s):</strong>
+                <a href="artifact.html">2.0.1</a>
+              </span>
+            </p>
+          </td>
+          <td>
+            <a href="#">Repair</a>
           </td>
         </tr>
       </table>
-      <h2>Errors</h2>
-      <p>
-        No errors found.
-      </p>
-      <h2>Warnings</h2>
+
+      <h2>Repository 2</h2>
+
       <p>
-        3 warnings found. (
+        Status:
+        <img src="images/icon_error_sml.gif" width="15" height="15" alt=""/>
+        0
+        <img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
+        1
+        (
         <a href="#">Repair all</a>
         )
       </p>
+
+      <h3>Artifacts</h3>
       <table>
         <tr>
-          <th>Group ID</th>
-          <th>Artifact ID</th>
-          <th>Version</th>
-          <th>Message</th>
-          <th></th>
-        </tr>
-        <tr>
-          <td>org.apache.maven</td>
-          <td>maven-model</td>
-          <td>2.0.1</td>
-          <td>File is missing SHA1 checksum</td>
           <td>
-            <a href="#">Repair</a>
+            <img src="images/icon_warning_sml.gif" width="15" height="15" alt=""/>
           </td>
-        </tr>
-        <tr>
-          <td>org.apache.maven</td>
-          <td>maven-model</td>
-          <td>2.0.2</td>
-          <td>File is missing SHA1 checksum</td>
           <td>
-            <span
-                style="color: green; font-weight: bold">Fixed
-            </span>
+            File is missing a digital signature
+            <p>
+              <span style="font-size: x-small">
+                <strong>Group ID:</strong>
+                <a href="browse2.html">org</a>
+                /
+                <a href="browse2.html">apache</a>
+                /
+                <a href="browse2.html">maven</a>
+                <strong>Artifact ID:</strong>
+                <a href="browse3.html">maven-artifact</a>
+                <strong>Version(s):</strong>
+                <a href="artifact.html">2.0.1</a>
+              </span>
+            </p>
           </td>
-        </tr>
-        <tr>
-          <td>org.apache.maven</td>
-          <td>maven-model</td>
-          <td>2.0.2</td>
-          <td>File is missing a digital signature</td>
           <td>
             <span style="color: gray">No fix available</span>
           </td>
         </tr>
       </table>
-      <table>
-
-      </table>
     </div>
   </body>
 </document>