You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by ld...@apache.org on 2012/02/10 15:13:31 UTC

svn commit: r1242780 - in /karaf/webconsole/trunk/core/src: main/java/org/apache/karaf/webconsole/core/ main/java/org/apache/karaf/webconsole/core/brand/ main/java/org/apache/karaf/webconsole/core/internal/ main/java/org/apache/karaf/webconsole/core/na...

Author: ldywicki
Date: Fri Feb 10 14:13:29 2012
New Revision: 1242780

URL: http://svn.apache.org/viewvc?rev=1242780&view=rev
Log:
Change look & feel of base pages to use twitter bootstrap.
Fix tests, remove unecessary files.
Refactored header of page.
Clean up of stylesheets / resources.
Add bootstrap based feedback panel (many thanks to topriddy from #wicket)

Added:
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageChangeLink.java
      - copied, changed from r1242778, karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LogoutLink.java
      - copied, changed from r1242778, karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertType.java
      - copied, changed from r1242778, karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.java
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.html
      - copied, changed from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.html
      - copied, changed from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.html
      - copied, changed from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.html
      - copied, changed from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html
Removed:
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.java
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/NavigationPanel.properties
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/NavigationPanel_de.properties
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/NavigationPanel_fr.properties
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/grid.css
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/tabs/bg.gif
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/tabs/left.gif
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/tabs/left_on.gif
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/tabs/right.gif
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/tabs/right_on.gif
Modified:
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/BasePage.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/internal/WebConsoleApplication.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java
    karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/util/LinkUtils.java
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/BasePage.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/LoginPage.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SecuredPage.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SidebarPage.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html
    karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/style.css
    karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/BasePageTest.java
    karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/WebConsoleTest.java
    karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/BasePage.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/BasePage.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/BasePage.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/BasePage.java Fri Feb 10 14:13:29 2012
@@ -21,13 +21,11 @@ import java.util.List;
 import java.util.Locale;
 
 import org.apache.karaf.webconsole.core.brand.BrandProvider;
-import org.apache.karaf.webconsole.core.dashboard.DashboardPage;
-import org.apache.karaf.webconsole.core.internal.LanguagePanel;
+import org.apache.karaf.webconsole.core.navigation.markup.LanguageTopPanel;
 import org.apache.wicket.behavior.IBehavior;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.util.ListModel;
 import org.ops4j.pax.wicket.api.PaxWicketBean;
@@ -47,19 +45,19 @@ public class BasePage extends WebPage {
     private IModel<List<Locale>> supportedLocales = new ListModel<Locale>(Arrays.asList(Locale.FRENCH, Locale.ENGLISH));
 
     public BasePage() {
-        Link<DashboardPage> homeLink = new BookmarkablePageLink<DashboardPage>("homeLink", DashboardPage.class);
-        homeLink.add(brandProvider.getHeaderImage("logo"));
-        add(homeLink);
+        add(createTopPanel("topPanel"));
 
         add(new Label("footer", "Apache Karaf Console"));
 
-        add(new LanguagePanel("languagePanel", supportedLocales));
-
         for (IBehavior behavior : brandProvider.getBehaviors()) {
             add(behavior);
         }
     }
 
+    protected Panel createTopPanel(String id) {
+        return new LanguageTopPanel(id, getSupportedLocales());
+    }
+
     @Override
     protected void onConfigure() {
         brandProvider.modify(this);
@@ -67,4 +65,7 @@ public class BasePage extends WebPage {
         super.onConfigure();
     }
 
+    protected IModel<List<Locale>> getSupportedLocales() {
+        return supportedLocales;
+    }
 }

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/brand/DefaultBrandProvider.java Fri Feb 10 14:13:29 2012
@@ -54,7 +54,6 @@ public class DefaultBrandProvider implem
 
     public void modify(Page page) {
         page.add(getHeaderContribution(BasePage.class, "style.css"));
-        page.add(getHeaderContribution(BasePage.class, "grid.css"));
     }
 
 }

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/internal/WebConsoleApplication.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/internal/WebConsoleApplication.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/internal/WebConsoleApplication.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/internal/WebConsoleApplication.java Fri Feb 10 14:13:29 2012
@@ -48,6 +48,7 @@ public class WebConsoleApplication exten
         getApplicationSettings().setPageExpiredErrorPage(PageExpiredErrorPage.class);
 
         getSecuritySettings().setAuthorizationStrategy(new RoleAuthorizationStrategy(new HierarchicalRoleCheckingStrategy()));
+        getMarkupSettings().setStripWicketTags(true);
     }
 
     /**

Added: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.java?rev=1242780&view=auto
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.java (added)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.java Fri Feb 10 14:13:29 2012
@@ -0,0 +1,30 @@
+package org.apache.karaf.webconsole.core.navigation.markup;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.karaf.webconsole.core.brand.BrandProvider;
+import org.apache.karaf.webconsole.core.dashboard.DashboardPage;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.ops4j.pax.wicket.api.PaxWicketBean;
+
+public class AnonymousTopPanel extends Panel {
+
+    private static final long serialVersionUID = 1L;
+
+    @PaxWicketBean(name = "brandProvider")
+    private BrandProvider brandProvider;
+
+    public AnonymousTopPanel(String id, IModel<List<Locale>> locales) {
+        super(id, locales);
+
+        Link<DashboardPage> homeLink = new BookmarkablePageLink<DashboardPage>("homeLink", DashboardPage.class);
+        //homeLink.add(brandProvider.getHeaderImage("logo"));
+        add(homeLink);
+        add(brandProvider.getHeaderImage("logo"));
+    }
+
+}

Copied: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageChangeLink.java (from r1242778, karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java)
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageChangeLink.java?p2=karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageChangeLink.java&p1=karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java&r1=1242778&r2=1242780&rev=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageChangeLink.java Fri Feb 10 14:13:29 2012
@@ -14,17 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.core.page;
+package org.apache.karaf.webconsole.core.navigation.markup;
 
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
+import java.util.Locale;
+
+import org.apache.wicket.markup.html.link.Link;
 
 /**
- * Page which body uses all available space - all screen width.
+ * Utility link to change session locale.
  */
-public class SinglePage extends SecuredPage {
+public class LanguageChangeLink extends Link<Void> {
+
+    private static final long serialVersionUID = 1L;
 
-    public SinglePage() {
-        add(new FeedbackPanel("feedback"));
+    private final Locale locale;
+
+    public LanguageChangeLink(String id, Locale locale) {
+        super(id);
+        this.locale = locale;
     }
 
+    @Override
+    public void onClick() {
+        getSession().setLocale(locale);
+    }
 }

Added: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.java?rev=1242780&view=auto
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.java (added)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.java Fri Feb 10 14:13:29 2012
@@ -0,0 +1,53 @@
+package org.apache.karaf.webconsole.core.navigation.markup;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.karaf.webconsole.core.BasePage;
+import org.apache.wicket.ResourceReference;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.image.Image;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.IModel;
+
+public class LanguageTopPanel extends AnonymousTopPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public LanguageTopPanel(String id, IModel<List<Locale>> locales) {
+        super(id, locales);
+
+        add(new ListView<Locale>("languages", locales) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void populateItem(final ListItem<Locale> item) {
+                final Locale model = item.getModelObject();
+
+                Link<Void> link = new LanguageChangeLink("languageLink", model);
+                link.add(getImage("flag", model));
+                link.add(getLabel("label", model));
+                item.add(link);
+            }
+        });
+    }
+
+    protected Label getLabel(String id, Locale locale) {
+        return new Label(id, locale.getDisplayName());
+    }
+
+    protected Image getImage(String id, Locale locale) {
+        String localeName = locale.getDisplayName(Locale.ENGLISH);
+        ResourceReference resource = new ResourceReference(BasePage.class, "images/" + localeName.toLowerCase() + "-flag.png");
+        Image image = new Image(id, resource);
+        image.add(new SimpleAttributeModifier("width", "20"));
+        image.add(new SimpleAttributeModifier("height", "14"));
+        image.add(new SimpleAttributeModifier("alt", localeName));
+        image.add(new SimpleAttributeModifier("title", localeName));
+        return image;
+    }
+}

Copied: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LogoutLink.java (from r1242778, karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java)
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LogoutLink.java?p2=karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LogoutLink.java&p1=karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java&r1=1242778&r2=1242780&rev=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/LogoutLink.java Fri Feb 10 14:13:29 2012
@@ -14,17 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.core.page;
+package org.apache.karaf.webconsole.core.navigation.markup;
 
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
+import org.apache.karaf.webconsole.core.page.LoginPage;
+import org.apache.karaf.webconsole.core.security.WebConsoleSession;
+import org.apache.wicket.markup.html.link.Link;
 
 /**
- * Page which body uses all available space - all screen width.
+ * Utility link to destroy session.
  */
-public class SinglePage extends SecuredPage {
+public class LogoutLink extends Link<Void> {
 
-    public SinglePage() {
-        add(new FeedbackPanel("feedback"));
+    public LogoutLink(String id) {
+        super(id);
+    }
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    public void onClick() {
+        WebConsoleSession.get().invalidateNow();
+        getRequestCycle().setRedirect(true);
+        setResponsePage(LoginPage.class);
     }
 
 }

Added: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.java?rev=1242780&view=auto
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.java (added)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.java Fri Feb 10 14:13:29 2012
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.webconsole.core.navigation.markup;
+
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider;
+import org.apache.karaf.webconsole.core.page.AvatarImage;
+import org.apache.karaf.webconsole.core.preferences.PreferencesPage;
+import org.apache.karaf.webconsole.core.security.SecuredPageLink;
+import org.apache.karaf.webconsole.core.security.WebConsoleSession;
+import org.apache.karaf.webconsole.core.util.LinkUtils;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.repeater.RepeatingView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.StringResourceModel;
+import org.ops4j.pax.wicket.api.PaxWicketBean;
+import org.osgi.service.prefs.PreferencesService;
+
+/**
+ * Component responsible for rendering top navigation in webconsole.
+ */
+public class NavigationTopPanel extends LanguageTopPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    @PaxWicketBean(name = "preferencesService")
+    private PreferencesService preferences;
+
+    public NavigationTopPanel(String id, IModel<List<Locale>> locales, IModel<List<ConsoleTabProvider>> model) {
+        super(id, locales);
+
+        add(createTabList(model));
+
+        String username = WebConsoleSession.get().getUsername();
+        add(new AvatarImage("avatar", preferences.getUserPreferences(username)));
+
+        add(new Label("username", username));
+        add(new SecuredPageLink<PreferencesPage>("preferencesLink", PreferencesPage.class));
+
+        Link<Void> aLink = new LogoutLink("logoutLink");
+        aLink.add(new Label("label", new StringResourceModel("logout.link", this.getDefaultModel())));
+        add(aLink);
+
+    }
+
+    private Component createTabList(IModel<List<ConsoleTabProvider>> model) {
+        return new ListView<ConsoleTabProvider>("tabs", model) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void populateItem(ListItem<ConsoleTabProvider> item) {
+                ConsoleTabProvider tab = item.getModelObject();
+
+                List<Link<Page>> items = tab.getItems("link", "label");
+                if (!items.isEmpty()) {
+                    populateTabItem(item, tab);
+                    populateTabChildren(item, items);
+                } else {
+                    populateSingleTabItem(item, tab);
+                }
+            }
+        };
+    }
+
+    protected void populateTabItem(ListItem<ConsoleTabProvider> item, ConsoleTabProvider provider) {
+        Link<Page> link = provider.getModuleLink("moduleLink", "moduleLabel");
+        item.add(link);
+
+        if (LinkUtils.isActiveTrail(link, this)) {
+            item.add(new AttributeAppender("class", Model.of("active"), " "));
+        }
+    }
+
+    protected void populateSingleTabItem(ListItem<ConsoleTabProvider> item, ConsoleTabProvider provider) {
+        Link<Page> moduleLink = provider.getModuleLink("moduleLink", "moduleLabel");
+        
+        // remove dropdown stuff
+        item.add(new SimpleAttributeModifier("class", ""));
+        moduleLink.add(new SimpleAttributeModifier("data-toggle", ""));
+        moduleLink.add(new SimpleAttributeModifier("class", ""));
+
+        if (LinkUtils.isActiveTrail(moduleLink, this)) {
+            item.add(new AttributeAppender("class", Model.of("active"), " "));
+        }
+
+        item.add(moduleLink);
+        item.add(new RepeatingView("moduleLinks"));
+    }
+
+    protected void populateTabChildren(ListItem<ConsoleTabProvider> item, List<Link<Page>> listItems) {
+        item.add(new ListView<Link<Page>>("moduleLinks", listItems) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void populateItem(ListItem<Link<Page>> item) {
+                item.add(item.getModelObject());
+            }
+        });
+    }
+}

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SecuredPage.java Fri Feb 10 14:13:29 2012
@@ -20,17 +20,11 @@ import java.util.List;
 
 import org.apache.karaf.webconsole.core.BasePage;
 import org.apache.karaf.webconsole.core.navigation.ConsoleTabProvider;
-import org.apache.karaf.webconsole.core.navigation.markup.NavigationPanel;
-import org.apache.karaf.webconsole.core.preferences.PreferencesPage;
-import org.apache.karaf.webconsole.core.security.SecuredPageLink;
-import org.apache.karaf.webconsole.core.security.WebConsoleSession;
+import org.apache.karaf.webconsole.core.navigation.markup.NavigationTopPanel;
 import org.apache.wicket.authorization.strategies.role.annotations.AuthorizeInstantiation;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.LoadableDetachableModel;
-import org.apache.wicket.model.StringResourceModel;
 import org.ops4j.pax.wicket.api.PaxWicketBean;
-import org.osgi.service.prefs.PreferencesService;
 
 /**
  * Page which requires admin role, in other words authorized user.
@@ -41,39 +35,15 @@ public class SecuredPage extends BasePag
     @PaxWicketBean(name = "tabs")
     private List<ConsoleTabProvider> tabs;
 
-    @PaxWicketBean(name = "preferencesService")
-    private PreferencesService preferences;
-
-    public SecuredPage() {
-        add(new NavigationPanel("navigationPanel", new LoadableDetachableModel<List<ConsoleTabProvider>>() {
-
+    @Override
+    protected Panel createTopPanel(String id) {
+        return new NavigationTopPanel(id, getSupportedLocales(), new LoadableDetachableModel<List<ConsoleTabProvider>>() {
             private static final long serialVersionUID = 1L;
 
             @Override
             protected List<ConsoleTabProvider> load() {
                 return tabs;
             }
-        }));
-
-        String username = WebConsoleSession.get().getUsername();
-        add(new AvatarImage("avatar", preferences.getUserPreferences(username)));
-
-        add(new Label("username", username));
-        add(new SecuredPageLink<PreferencesPage>("preferencesLink", PreferencesPage.class));
-
-        Link<Void> aLink = new Link<Void>("logoutLink") {
-
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public void onClick() {
-                WebConsoleSession.get().invalidateNow();
-                getRequestCycle().setRedirect(true);
-                setResponsePage(LoginPage.class);
-            }
-        };
-
-        aLink.add(new Label("logoutTranslatedLink", new StringResourceModel("logout.link", this.getDefaultModel())));
-        add(aLink);
+        });
     }
 }

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SidebarPage.java Fri Feb 10 14:13:29 2012
@@ -18,7 +18,7 @@ package org.apache.karaf.webconsole.core
 
 import org.apache.karaf.webconsole.core.internal.SidebarPanel;
 import org.apache.karaf.webconsole.core.navigation.SidebarProvider;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
+import org.apache.karaf.webconsole.core.panel.feedback.BootstrapFeedbackPanel;
 import org.apache.wicket.markup.html.panel.Panel;
 
 /**
@@ -30,7 +30,7 @@ public class SidebarPage extends Secured
     private Panel sidebar;
 
     public SidebarPage() {
-        add(new FeedbackPanel("feedback"));
+        add(new BootstrapFeedbackPanel("feedback"));
     }
 
     protected void setSidebarProvider(SidebarProvider provider) {

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/page/SinglePage.java Fri Feb 10 14:13:29 2012
@@ -16,7 +16,7 @@
  */
 package org.apache.karaf.webconsole.core.page;
 
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
+import org.apache.karaf.webconsole.core.panel.feedback.BootstrapFeedbackPanel;
 
 /**
  * Page which body uses all available space - all screen width.
@@ -24,7 +24,7 @@ import org.apache.wicket.markup.html.pan
 public class SinglePage extends SecuredPage {
 
     public SinglePage() {
-        add(new FeedbackPanel("feedback"));
+        add(new BootstrapFeedbackPanel("feedback"));
     }
 
 }

Added: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.java?rev=1242780&view=auto
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.java (added)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.java Fri Feb 10 14:13:29 2012
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.webconsole.core.panel.feedback;
+
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+
+/**
+ * Bootstrap based alert panel.
+ */
+public final class AlertPanel extends Panel {
+
+    private static final long serialVersionUID = 1L;
+
+    private WebMarkupContainer wrapper;
+
+    public AlertPanel(String id, String message, AlertType type) {
+        super(id);
+
+        // make sure that wrapper is added before type of alert is set
+        add(wrapper = new WebMarkupContainer("wrapper"));
+
+        setType(type); // setter will modify css class
+
+        wrapper.add(new Label("message", message));
+    }
+
+    public void setType(AlertType type) {
+        wrapper.add(new AttributeAppender("class", Model.of(type.getCssClass()), " "));
+    }
+
+}
\ No newline at end of file

Copied: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertType.java (from r1242778, karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java)
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertType.java?p2=karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertType.java&p1=karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java&r1=1242778&r2=1242780&rev=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/AlertType.java Fri Feb 10 14:13:29 2012
@@ -14,26 +14,41 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.karaf.webconsole.core.preferences.util;
-
-import org.osgi.service.prefs.Preferences;
-import org.osgi.service.prefs.PreferencesService;
+package org.apache.karaf.webconsole.core.panel.feedback;
 
 /**
- * Preferences service created on top of standard JDK implementation.
+ * Enumeration which contains style names for alert panel. It points directly to
+ * bootstrap css classes.
  */
-public class JdkPreferencesService implements PreferencesService {
+public enum AlertType {
 
-    public Preferences getSystemPreferences() {
-        return new JdkPreferences(java.util.prefs.Preferences.systemRoot());
-    }
+    /**
+     * By default alert is orange, we don't need any additional classes.
+     */
+    WARNING(""),
+
+    /**
+     * Red background.
+     */
+    ERROR("alert-error"),
+
+    /**
+     * Green background.
+     */
+    SUCCESS("alert-success"),
+
+    /**
+     * Blue background
+     */
+    INFO("alert-info");
 
-    public Preferences getUserPreferences(String name) {
-        return new JdkPreferences(java.util.prefs.Preferences.userRoot());
-    }
+    private String cssClass;
 
-    public String[] getUsers() {
-        return new String[] { System.getProperty("user.name") };
+    AlertType(String css) {
+        this.cssClass = css;
     }
 
+    public String getCssClass() {
+        return cssClass;
+    }
 }

Added: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.java?rev=1242780&view=auto
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.java (added)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.java Fri Feb 10 14:13:29 2012
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.webconsole.core.panel.feedback;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.feedback.FeedbackMessage;
+import org.apache.wicket.markup.html.panel.FeedbackPanel;
+
+/**
+ * Feedback panel which produces bootstrap-like message entries.
+ */
+public class BootstrapFeedbackPanel extends FeedbackPanel {
+
+    private static final long serialVersionUID = 1L;
+
+    public BootstrapFeedbackPanel(String id) {
+        super(id);
+    }
+
+    @Override
+    protected Component newMessageDisplayComponent(String id, FeedbackMessage message) {
+        // by default we'll assign alert-error class
+        AlertPanel alertPanel = new AlertPanel(id, message.getMessage().toString(), AlertType.ERROR);
+
+        // depends on message level change the css class
+        switch (message.getLevel()) {
+            case FeedbackMessage.INFO:
+                alertPanel.setType(AlertType.INFO);
+                break;
+            case FeedbackMessage.WARNING:
+                alertPanel.setType(AlertType.WARNING);
+                break;
+            // Not supported in Wicket 1.4
+//            case FeedbackMessage.SUCCESS:
+//                alertPanel.setType(AlertType.SUCCESS);
+//                break;
+        }
+
+        return alertPanel;
+    }
+
+}
\ No newline at end of file

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/preferences/util/JdkPreferencesService.java Fri Feb 10 14:13:29 2012
@@ -16,13 +16,17 @@
  */
 package org.apache.karaf.webconsole.core.preferences.util;
 
+import java.io.Serializable;
+
 import org.osgi.service.prefs.Preferences;
 import org.osgi.service.prefs.PreferencesService;
 
 /**
  * Preferences service created on top of standard JDK implementation.
  */
-public class JdkPreferencesService implements PreferencesService {
+public class JdkPreferencesService implements PreferencesService, Serializable /* for tests*/ {
+
+    private static final long serialVersionUID = 1L;
 
     public Preferences getSystemPreferences() {
         return new JdkPreferences(java.util.prefs.Preferences.systemRoot());

Modified: karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/util/LinkUtils.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/util/LinkUtils.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/util/LinkUtils.java (original)
+++ karaf/webconsole/trunk/core/src/main/java/org/apache/karaf/webconsole/core/util/LinkUtils.java Fri Feb 10 14:13:29 2012
@@ -16,7 +16,9 @@
  */
 package org.apache.karaf.webconsole.core.util;
 
+import org.apache.wicket.Component;
 import org.apache.wicket.Page;
+import org.apache.wicket.RequestCycle;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
 import org.apache.wicket.markup.html.link.Link;
@@ -44,4 +46,22 @@ public abstract class LinkUtils {
         return link;
     }
 
+    /**
+     * Checks if given link is in active trail. It detects a path only from
+     * bookmarkable links.
+     * 
+     * @param link Link.
+     * @param component Component which should be asked for rendering url.
+     * @return True if link path is contained in request path.
+     */
+    public static boolean isActiveTrail(Link<?> link, Component component) {
+        if (link instanceof BookmarkablePageLink) {
+            Class<? extends Page> pageClass = ((BookmarkablePageLink<?>) link).getPageClass();
+
+            String requestPath = RequestCycle.get().getRequest().getPath();
+            String linkPath = (component.urlFor(pageClass, null) + "").replace("../", "");
+            return requestPath.contains(linkPath);
+        }
+        return false;
+    }
 }

Modified: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/BasePage.html
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/BasePage.html?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/BasePage.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/BasePage.html Fri Feb 10 14:13:29 2012
@@ -23,22 +23,13 @@
 </head>
 
 <body>
-    <div class="container container_12">
-        <div class="grid_3">
-            <a wicket:id="homeLink">
-                <img wicket:id="logo" />
-            </a>
-        </div>
-        <div class="grid_9">
-            <h3>Administration console</h3>
+    <div class="container-fluid">
 
-            <div wicket:id="languagePanel" id="languages">Languages go here</div>
-        </div>
-        <div class="clear"></div>
+        <div wicket:id="topPanel"></div>
 
         <wicket:child />
 
-        <div class="grid_12">
+        <div class="row-fluid">
             <div wicket:id="footer">Footer</div>
         </div>
     </div>

Copied: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.html (from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html)
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.html?p2=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.html&p1=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html&r1=1242778&r2=1242780&rev=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/AnonymousTopPanel.html Fri Feb 10 14:13:29 2012
@@ -16,21 +16,28 @@
    limitations under the License.
 -->
 <wicket:panel xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <div id="topmenu">
-        <ul>
-            <li wicket:id="tabs">
-                <a wicket:id="moduleLink">
-                    <span wicket:id="moduleLabel">Category</span>
+
+    <div class="navbar navbar-fixed-top">
+        <div class="navbar-inner">
+            <div class="container-fluid">
+
+                <!-- This part is visible for mobile devices -->
+                <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+                    <span class="icon-bar"></span>
+                    <span class="icon-bar"></span>
+                    <span class="icon-bar"></span>
+                </a>
+
+                <a class="brand" wicket:id="homeLink">
+                    WebConsole
                 </a>
 
-                <ul>
-                    <li wicket:id="moduleLinks">
-                        <a wicket:id="link">
-                            <span wicket:id="label">Label</span>
-                        </a>
-                    </li>
-                </ul>
-            </li>
-        </ul>
+                <wicket:child />
+            </div>
+        </div>
+    </div>
+    <div class="pull-right">
+        <img wicket:id="logo" />
     </div>
+
 </wicket:panel>
\ No newline at end of file

Copied: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.html (from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html)
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.html?p2=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.html&p1=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html&r1=1242778&r2=1242780&rev=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/LanguageTopPanel.html Fri Feb 10 14:13:29 2012
@@ -15,22 +15,25 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<wicket:panel xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <div id="topmenu">
-        <ul>
-            <li wicket:id="tabs">
-                <a wicket:id="moduleLink">
-                    <span wicket:id="moduleLabel">Category</span>
-                </a>
+<wicket:extend xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+    <div class="nav-collapse"><!-- Inner navigation -->
+        <wicket:child /><!-- make extensions be rendered first -->
 
-                <ul>
-                    <li wicket:id="moduleLinks">
-                        <a wicket:id="link">
-                            <span wicket:id="label">Label</span>
+        <ul class="nav pull-right">
+            <li class="dropdown">
+                <a class="dropdown-toggle" data-toggle="dropdown">
+                    Language <b class="caret"></b>
+                </a>
+                <ul class="dropdown-menu">
+                    <li wicket:id="languages">
+                        <a wicket:id="languageLink">
+                            <img wicket:id="flag" />
+                            <span wicket:id="label">English</span>
                         </a>
                     </li>
                 </ul>
             </li>
+
         </ul>
     </div>
-</wicket:panel>
\ No newline at end of file
+</wicket:extend>
\ No newline at end of file

Added: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.html
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.html?rev=1242780&view=auto
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.html (added)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationTopPanel.html Fri Feb 10 14:13:29 2012
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<wicket:extend xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+
+    <ul class="nav">
+        <li wicket:id="tabs" class="dropdown">
+            <a wicket:id="moduleLink" class="dropdown-toggle" data-toggle="dropdown">
+                <span wicket:id="moduleLabel">Category</span>
+                <b class="caret"></b>
+            </a>
+            <ul class="dropdown-menu">
+                <li wicket:id="moduleLinks">
+                    <a wicket:id="link">
+                        <span wicket:id="label">Label</span>
+                    </a>
+                </li>
+            </ul>
+        </li>
+        <li class="divider-vertical"></li>
+    </ul>
+
+    <wicket:child />
+
+    <ul class="nav pull-right">
+        <li class="dropdown active">
+            <a href="#" data-toggle="dropdown" class="dropdown-toggle">
+                <span wicket:id="username">Admin</span>
+                <b class="caret"></b>
+            </a>
+            <ul class="dropdown-menu">
+                <li>
+                    <img wicket:id="avatar" />
+                    <a wicket:id="preferencesLink">Preferences</a>
+                </li>
+            </ul>
+        </li>
+        <li>
+            <a wicket:id="logoutLink">
+                <span wicket:id="label">Logout</span>
+            </a>
+        </li>
+        
+    </ul>
+
+</wicket:extend>
\ No newline at end of file

Modified: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/LoginPage.html
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/LoginPage.html?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/LoginPage.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/LoginPage.html Fri Feb 10 14:13:29 2012
@@ -16,11 +16,13 @@
    limitations under the License.
 -->
 <wicket:extend xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <br /><br /><br /><br /><br /><br />
-    <div class="grid_4 prefix_4 suffix_4">
-        <div wicket:id="signIn">
-            Here will be sign in form.
+    <div class="row-fluid" style="margin-top: 150px; margin-bottom: 150px">
+        <span class="span4">&nbsp;</span>
+        <div class="span4">
+            <div wicket:id="signIn">
+                Here will be sign in form.
+            </div>
         </div>
+        <span class="span4">&nbsp;</span>
     </div>
-    <br /><br /><br /><br /><br /><br />
 </wicket:extend>
\ No newline at end of file

Modified: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SecuredPage.html
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SecuredPage.html?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SecuredPage.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SecuredPage.html Fri Feb 10 14:13:29 2012
@@ -16,20 +16,6 @@
    limitations under the License.
 -->
 <wicket:extend xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <div id="userbox" class="grid_2">
-        <img wicket:id="avatar" class="avatar" alt="User avatar" />
-        <span id="details">
-            Welcome <span wicket:id="username">admin</span>
-
-            <a href="#" wicket:id="logoutLink"><span wicket:id="logoutTranslatedLink"/></a>
-            <a href="#" wicket:id="preferencesLink">Preferences</a>
-        </span>
-    </div>
-
-    <div class="grid_12">
-        <div wicket:id="navigationPanel">Navigation goes here</div>
-    </div>
-    <div class="clear"></div>
 
     <wicket:child />
 

Modified: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SidebarPage.html
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SidebarPage.html?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SidebarPage.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SidebarPage.html Fri Feb 10 14:13:29 2012
@@ -16,12 +16,15 @@
    limitations under the License.
 -->
 <wicket:extend xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <div class="grid_3 sidebar-wrapper">
-        <div class="sidebar" wicket:id="sidebar">Sidebar goes here</div>
+
+    <div class="row-fluid">
+        <div class="span4">
+            <div class="sidebar" wicket:id="sidebar">Sidebar goes here</div>
+        </div>
+        <div class="span8">
+            <span wicket:id="feedback">Feedback stuff</span>
+            <wicket:child />
+        </div>
     </div>
-    <div class="grid_9 sidebar-content content">
-        <span wicket:id="feedback">Feedback stuff</span>
-        <wicket:child />
-    </div>
-    <div class="clear"></div>
+
 </wicket:extend>
\ No newline at end of file

Modified: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html Fri Feb 10 14:13:29 2012
@@ -16,9 +16,10 @@
    limitations under the License.
 -->
 <wicket:extend xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <div class="grid_12 single-content content">
+
+    <div class="row-fluid">
         <span wicket:id="feedback">Feedback stuff</span>
         <wicket:child />
     </div>
-    <div class="clear"></div>
+
 </wicket:extend>
\ No newline at end of file

Copied: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.html (from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html)
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.html?p2=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.html&p1=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html&r1=1242778&r2=1242780&rev=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/page/SinglePage.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/AlertPanel.html Fri Feb 10 14:13:29 2012
@@ -15,10 +15,11 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 -->
-<wicket:extend xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <div class="grid_12 single-content content">
-        <span wicket:id="feedback">Feedback stuff</span>
-        <wicket:child />
+<wicket:panel xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
+    <div wicket:id="wrapper" class="alert">
+        <a class="close" href="#" data-dismiss="alert" >&times;</a>
+        <p>
+            <span wicket:id="message"></span>
+        </p>
     </div>
-    <div class="clear"></div>
-</wicket:extend>
\ No newline at end of file
+</wicket:panel>
\ No newline at end of file

Copied: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.html (from r1242778, karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html)
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.html?p2=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.html&p1=karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html&r1=1242778&r2=1242780&rev=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/navigation/markup/NavigationPanel.html (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/panel/feedback/BootstrapFeedbackPanel.html Fri Feb 10 14:13:29 2012
@@ -16,21 +16,9 @@
    limitations under the License.
 -->
 <wicket:panel xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd">
-    <div id="topmenu">
-        <ul>
-            <li wicket:id="tabs">
-                <a wicket:id="moduleLink">
-                    <span wicket:id="moduleLabel">Category</span>
-                </a>
-
-                <ul>
-                    <li wicket:id="moduleLinks">
-                        <a wicket:id="link">
-                            <span wicket:id="label">Label</span>
-                        </a>
-                    </li>
-                </ul>
-            </li>
-        </ul>
+    <div wicket:id="feedbackul">
+        <div wicket:id="messages">
+            <div wicket:id="message"></div>
+        </div>
     </div>
 </wicket:panel>
\ No newline at end of file

Modified: karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/style.css
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/style.css?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/style.css (original)
+++ karaf/webconsole/trunk/core/src/main/resources/org/apache/karaf/webconsole/core/style.css Fri Feb 10 14:13:29 2012
@@ -1,14 +1,10 @@
 * {
-    font-family: Arial, Tahoma;
     font-size: 16px;
 }
 
 body {
-    background: #FFFFFF;
-}
-
-a {
-    color: #0F3B5F;
+    margin-top: 65px;
+    background: #fff;
 }
 
 li.current {
@@ -19,77 +15,6 @@ div.widget {
     border: 1px dotted black;
 }
 
-#container {
-    float: left;
-    width: 1500px;
-    margin: 0 auto;
-}
-
-#sidebar {
-    float: left;
-    width: 250px;
-}
-
-#userbox {
-    float: right;
-    width: 250px;
-}
-
-#userbox img.avatar {
-    padding: 3px;
-    float: left;
-}
-
-#details {
-    display: block;
-    float: left;
-}
-
-#details span {
-    font-weight: bold;
-}
-
-#details a span {
-    font-weight: normal;
-}
-
-#sidebar ul li, #languages ul li {
-    list-style-type: none;
-}
-
-#languages ul li a:link {
-    text-decoration: none;
-}
-
-#languages ul li {
-    display: inline;
-}
-
-#topmenu ul li, #top-panel ul li {
-    display: inline;
-}
-
-#topmenu {
-    background: #6f83ab;
-}
-
-#top-panel ul {
-    margin: 0px;
-}
-
-#top-panel {
-    background: #CCCC00;
-}
-
-table.dataview {
-	width: 100%;
-	margin-top: 20px;
-	margin-bottom: 10px;
-	border-bottom: 1px solid #0079d6;
-	font-size: 1em;
-	font-family: arial;
-}
-
 table.dataview caption { text-align: left; }
 table.dataview tr { padding-top: 2px; padding-bottom: 2px; }
 table.dataview tr.even { background-color: #ffebcd; }
@@ -109,51 +34,3 @@ table.dataview tr th a { font-weight: no
 table.dataview #message { padding-left: 3px; }
 table.dataview caption { padding-bottom: 2px; }
 
-div.tabpanel div.tab-row{
-  float:left;
-  width:100%;
-  background:#DAE0D2 url("tabs/bg.gif") repeat-x bottom;
-  line-height:normal;
-  }
-
-div.tabpanel div.tab-row ul {
-  margin:0;
-  padding:10px 10px 0;
-  list-style:none;
-  }
-
-div.tabpanel div.tab-row li {
-  float:left;
-  background:url("tabs/left.gif") no-repeat left top;
-  margin:0;
-  padding:0 0 0 9px;
-  }
-
-div.tabpanel div.tab-row a {
-  display:block;
-  background:url("tabs/right.gif") no-repeat right top;
-  padding:5px 15px 4px 6px;
-  text-decoration:none;
-  font-weight:bold;
-  white-space:nowrap;
-  color:#eee;
-  }
-
-div.tab-panel {
-	clear: left;
-}
-
-div.tabpanel div.tab-row a:hover {
-  color:#fff;
-  }
-
-div.tabpanel div.tab-row li.selected {
-  background-image:url("tabs/left_on.gif");
-  }
-
-div.tabpanel div.tab-row li.selected a {
-  background-image:url("tabs/right_on.gif");
-  color:#333;
-  padding-bottom:5px;
-}
-

Modified: karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/BasePageTest.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/BasePageTest.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/BasePageTest.java (original)
+++ karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/BasePageTest.java Fri Feb 10 14:13:29 2012
@@ -68,7 +68,7 @@ public class BasePageTest extends WebCon
         WicketTester tester = new WicketTester(application);
         tester.startPage(BasePage.class);
 
-        tester.assertVisible("homeLink:" + imageId);
+        tester.assertVisible("topPanel:" + imageId);
 
         verify(brandProvider);
     }

Modified: karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/WebConsoleTest.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/WebConsoleTest.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/WebConsoleTest.java (original)
+++ karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/WebConsoleTest.java Fri Feb 10 14:13:29 2012
@@ -32,8 +32,6 @@ import org.apache.wicket.authentication.
 import org.apache.wicket.markup.html.link.Link;
 import org.apache.wicket.protocol.http.WebApplication;
 import org.junit.Before;
-import org.osgi.service.prefs.Preferences;
-import org.osgi.service.prefs.PreferencesService;
 
 /**
  * Base class for webconsole tests.

Modified: karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java
URL: http://svn.apache.org/viewvc/karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java?rev=1242780&r1=1242779&r2=1242780&view=diff
==============================================================================
--- karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java (original)
+++ karaf/webconsole/trunk/core/src/test/java/org/apache/karaf/webconsole/core/page/SecuredPageTest.java Fri Feb 10 14:13:29 2012
@@ -59,7 +59,7 @@ public class SecuredPageTest extends Web
         WicketTester tester = new WicketTester(application);
 
         tester.startPage(SecuredPage.class);
-        tester.clickLink("logoutLink");
+        tester.clickLink("topPanel:logoutLink");
         tester.assertRenderedPage(LoginPage.class);
     }
 
@@ -76,8 +76,8 @@ public class SecuredPageTest extends Web
         List<ConsoleTabProvider> tabs = new ArrayList<ConsoleTabProvider>();
 
         SerializableConsoleTabProvider mock = createStrictMock(SerializableConsoleTabProvider.class);
-        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test", BasePage.class));
         expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test", BasePage.class));
 
         tabs.add(mock);
         values.put("tabs", tabs);
@@ -107,11 +107,11 @@ public class SecuredPageTest extends Web
         List<ConsoleTabProvider> tabs = new ArrayList<ConsoleTabProvider>();
 
         SerializableConsoleTabProvider mock = createStrictMock(SerializableConsoleTabProvider.class);
-        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test", BasePage.class));
         LinksAnswer answer = new LinksAnswer();
         answer.addLink("A1", SecuredPage.class);
         answer.addLink("B1", SidebarPage.class);
         expect(mock.getItems(anyString(), anyString())).andAnswer(answer);
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test", BasePage.class));
 
         tabs.add(mock);
         values.put("tabs", tabs);
@@ -124,8 +124,9 @@ public class SecuredPageTest extends Web
 
         assertTabs(tester, tabs);
         assertTabLink(tester, 0, "test", BasePage.class, answer.getPageLinks());
-        tester.assertLabel("navigationPanel:tabs:0:moduleLinks:0:link:label", "A1");
-        tester.assertLabel("navigationPanel:tabs:0:moduleLinks:1:link:label", "B1");
+
+        tester.assertLabel("topPanel:tabs:0:moduleLinks:0:link:label", "A1");
+        tester.assertLabel("topPanel:tabs:0:moduleLinks:1:link:label", "B1");
 
         verify(mock);
     }
@@ -143,27 +144,27 @@ public class SecuredPageTest extends Web
         List<ConsoleTabProvider> tabs = new ArrayList<ConsoleTabProvider>();
 
         SerializableConsoleTabProvider mock = createStrictMock(SerializableConsoleTabProvider.class);
-        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test1", BasePage.class));
         expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test1", BasePage.class));
         replay(mock);
         tabs.add(mock);
 
         mock = createStrictMock(SerializableConsoleTabProvider.class);
-        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test2", SecuredPage.class));
         expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test2", SecuredPage.class));
         replay(mock);
         tabs.add(mock);
 
         mock = createStrictMock(SerializableConsoleTabProvider.class);
-        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test3", SinglePage.class));
         expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test3", SinglePage.class));
         replay(mock);
         tabs.add(mock);
 
 
         mock = createStrictMock(SerializableConsoleTabProvider.class);
-        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test4", SidebarPage.class));
         expect(mock.getItems(anyString(), anyString())).andReturn(emptyLinkList());
+        expect(mock.getModuleLink(anyString(), anyString())).andAnswer(new LinkAnswer("test4", SidebarPage.class));
         replay(mock);
         tabs.add(mock);
 
@@ -185,7 +186,7 @@ public class SecuredPageTest extends Web
     // additional asserts
 
     private void assertTabs(WicketTester tester, List<ConsoleTabProvider> tabs) {
-        tester.assertListView("navigationPanel:tabs", tabs);
+        tester.assertListView("topPanel:tabs", tabs);
     }
 
     private void assertTabLink(WicketTester tester, int position, String label, Class<? extends WebPage> page) {
@@ -193,9 +194,11 @@ public class SecuredPageTest extends Web
     }
 
     private void assertTabLink(WicketTester tester, int position, String label, Class<? extends WebPage> page, List<Link<Page>> children) {
-        tester.assertLabel("navigationPanel:tabs:" + position + ":moduleLink:moduleLabel", label);
-        tester.assertBookmarkablePageLink("navigationPanel:tabs:" + position + ":moduleLink", page, "");
-        tester.assertListView("navigationPanel:tabs:" + position + ":moduleLinks", children);
+        tester.assertLabel("topPanel:tabs:" + position + ":moduleLink:moduleLabel", label);
+        tester.assertBookmarkablePageLink("topPanel:tabs:" + position + ":moduleLink", page, "");
+        if (!children.isEmpty()) {
+            tester.assertListView("topPanel:tabs:" + position + ":moduleLinks", children);
+        }
     }
 
     @Override