You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by ca...@apache.org on 2012/01/30 17:23:43 UTC

svn commit: r1237759 - in /incubator/rave/trunk: rave-components/rave-core/src/main/java/org/apache/rave/portal/service/ rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/ rave-components/rave-core/src/test/java/org/apache/rav...

Author: carlucci
Date: Mon Jan 30 16:23:43 2012
New Revision: 1237759

URL: http://svn.apache.org/viewvc?rev=1237759&view=rev
Log:
RAVE-435: Navigate Widget Repository via Category.  Applying patch supplied by Jacob Hilker

Modified:
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/WidgetService.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java
    incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultWidgetServiceTest.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java
    incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java
    incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties
    incubator/rave/trunk/rave-portal-resources/src/main/resources/messages_nl.properties
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/store.jsp
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/widget.jsp
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_store.js

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/WidgetService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/WidgetService.java?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/WidgetService.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/WidgetService.java Mon Jan 30 16:23:43 2012
@@ -167,4 +167,14 @@ public interface WidgetService {
      */
     SearchResult<Widget> getWidgetsByTag(String tagKeyWord, int offset, int pageSize);
 
+    /**
+     * Get a SearchResult for {@link Widget}s by category
+     * 
+     * @param categoryId category to search against
+     * @param offset     start point within the resultSet (for paging)
+     * @param pageSize   maximum number of items to be returned (for paging)
+     * @return           SearchResult
+     */
+    SearchResult<Widget> getWidgetsByCategory(long categoryId, int offset, int pageSize);
+
 }

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultWidgetService.java Mon Jan 30 16:23:43 2012
@@ -21,11 +21,13 @@ package org.apache.rave.portal.service.i
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.rave.exception.DuplicateItemException;
+import org.apache.rave.portal.model.Category;
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.model.Widget;
 import org.apache.rave.portal.model.WidgetStatus;
 import org.apache.rave.portal.model.util.SearchResult;
 import org.apache.rave.portal.model.util.WidgetStatistics;
+import org.apache.rave.portal.repository.CategoryRepository;
 import org.apache.rave.portal.repository.UserRepository;
 import org.apache.rave.portal.repository.WidgetRepository;
 import org.apache.rave.portal.service.WidgetService;
@@ -41,11 +43,13 @@ public class DefaultWidgetService implem
 
     private final WidgetRepository widgetRepository;
     private final UserRepository userRepository;
+    private final CategoryRepository categoryRepository;
 
     @Autowired
-    public DefaultWidgetService(WidgetRepository widgetRepository, UserRepository userRepository) {
+    public DefaultWidgetService(WidgetRepository widgetRepository, UserRepository userRepository, CategoryRepository categoryRepository) {
         this.widgetRepository = widgetRepository;
         this.userRepository = userRepository;
+        this.categoryRepository = categoryRepository;
     }
 
     @Override
@@ -174,4 +178,13 @@ public class DefaultWidgetService implem
         searchResult.setPageSize(pageSize);
         return searchResult;
     }
+
+    @Override
+    public SearchResult<Widget> getWidgetsByCategory(long categoryId, int offset, int pageSize) {
+        List<Widget> widgets = categoryRepository.get(categoryId).getWidgets();
+        SearchResult<Widget> searchResult = new SearchResult<Widget>(widgets, widgets.size());
+        searchResult.setOffset(offset);
+        searchResult.setPageSize(pageSize);
+        return searchResult;
+    }
 }

Modified: incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultWidgetServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultWidgetServiceTest.java?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultWidgetServiceTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/impl/DefaultWidgetServiceTest.java Mon Jan 30 16:23:43 2012
@@ -20,11 +20,13 @@
 package org.apache.rave.portal.service.impl;
 
 import org.apache.rave.exception.DuplicateItemException;
+import org.apache.rave.portal.model.Category;
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.model.Widget;
 import org.apache.rave.portal.model.WidgetStatus;
 import org.apache.rave.portal.model.util.SearchResult;
 import org.apache.rave.portal.model.util.WidgetStatistics;
+import org.apache.rave.portal.repository.CategoryRepository;
 import org.apache.rave.portal.repository.UserRepository;
 import org.apache.rave.portal.repository.WidgetRepository;
 import org.apache.rave.portal.service.WidgetService;
@@ -47,12 +49,14 @@ public class DefaultWidgetServiceTest {
     private WidgetService widgetService;
     private WidgetRepository widgetRepository;
     private UserRepository userRepository;
+    private CategoryRepository categoryRepository;
 
     @Before
     public void setup() {
         widgetRepository = createMock(WidgetRepository.class);
         userRepository = createMock(UserRepository.class);
-        widgetService = new DefaultWidgetService(widgetRepository, userRepository);
+        categoryRepository = createMock(CategoryRepository.class);
+        widgetService = new DefaultWidgetService(widgetRepository, userRepository, categoryRepository);
     }
 
     @Test
@@ -337,6 +341,29 @@ public class DefaultWidgetServiceTest {
         verify(widgetRepository);
     }
 
-
+    @Test
+    public void getWidgetsByCategory_valid(){
+        long id = 1L;
+        int offset = 0;
+        int pageSize = 10; 
+        String categoryText = "Social";
+        Widget w = new Widget();
+        List<Category> categories = new ArrayList<Category>();
+        Category c = new Category();
+        List<Widget> widgets = new ArrayList<Widget>();
+        widgets.add(w);
+        c.setWidgets(widgets);
+        c.setEntityId(id);
+        c.setText(categoryText);
+        categories.add(c);
+        w.setCategories(categories);
+        expect(categoryRepository.get(id)).andReturn(c);
+        replay(categoryRepository);
+        SearchResult<Widget> result = widgetService.getWidgetsByCategory(id,offset,pageSize);
+        verify(categoryRepository);
+        assertEquals("number of widgets", 1, result.getTotalResults());
+        assertSame(w, result.getResultSet().get(0));
+        assertEquals(c.getEntityId(), result.getResultSet().get(0).getCategories().get(0).getEntityId());
+    }
 
 }

Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/controller/WidgetStoreController.java Mon Jan 30 16:23:43 2012
@@ -23,11 +23,7 @@ import org.apache.rave.portal.model.Port
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.model.Widget;
 import org.apache.rave.portal.model.WidgetStatus;
-import org.apache.rave.portal.model.util.SearchResult;
-import org.apache.rave.portal.service.PortalPreferenceService;
-import org.apache.rave.portal.service.TagService;
-import org.apache.rave.portal.service.UserService;
-import org.apache.rave.portal.service.WidgetService;
+import org.apache.rave.portal.service.*;
 import org.apache.rave.portal.web.util.ModelKeys;
 import org.apache.rave.portal.web.util.PortalPreferenceKeys;
 import org.apache.rave.portal.web.util.ViewNames;
@@ -36,7 +32,6 @@ import org.springframework.beans.factory
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.WebDataBinder;
 import org.springframework.web.bind.annotation.*;
 
 @Controller
@@ -55,17 +50,19 @@ public class WidgetStoreController {
 
     private final TagService tagService;
 
+    private final CategoryService categoryService;
 
     @Autowired
     public WidgetStoreController(WidgetService widgetService, NewWidgetValidator validator,
                                  UserService userService, PortalPreferenceService preferenceService,
-                                 TagService tagService) {
+                                 TagService tagService,
+                                 CategoryService categoryService) {
         this.widgetService = widgetService;
         this.widgetValidator = validator;
         this.userService = userService;
         this.preferenceService = preferenceService;
         this.tagService=tagService;
-
+        this.categoryService=categoryService;
     }
 
     /**
@@ -80,11 +77,9 @@ public class WidgetStoreController {
     public String view(Model model, @RequestParam long referringPageId,
                        @RequestParam(required = false, defaultValue = "0") int offset) {
         User user = userService.getAuthenticatedUser();
+        widgetStoreModelHelper(model, referringPageId, user);
         model.addAttribute(ModelKeys.WIDGETS,
                 widgetService.getPublishedWidgets(offset, getPageSize()));
-        model.addAttribute(ModelKeys.REFERRING_PAGE_ID, referringPageId);
-        model.addAttribute(ModelKeys.WIDGETS_STATISTICS, widgetService.getAllWidgetStatistics(user.getEntityId()));
-        model.addAttribute(ModelKeys.TAGS, tagService.getAllTags());
         return ViewNames.STORE;
     }
 
@@ -92,11 +87,9 @@ public class WidgetStoreController {
     public String viewMine(Model model, @RequestParam long referringPageId,
                            @RequestParam(required = false, defaultValue = "0") int offset) {
         User user = userService.getAuthenticatedUser();
+        widgetStoreModelHelper(model, referringPageId, user);
         model.addAttribute(ModelKeys.WIDGETS,
                 widgetService.getWidgetsByOwner(user.getEntityId(), offset, getPageSize()));
-        model.addAttribute(ModelKeys.REFERRING_PAGE_ID, referringPageId);
-        model.addAttribute(ModelKeys.WIDGETS_STATISTICS, widgetService.getAllWidgetStatistics(user.getEntityId()));
-        model.addAttribute(ModelKeys.TAGS, tagService.getAllTags());
         return ViewNames.STORE;
     }
 
@@ -110,12 +103,11 @@ public class WidgetStoreController {
      */
     @RequestMapping(method = RequestMethod.GET, value = "widget/{widgetId}")
     public String viewWidget(Model model, @PathVariable long widgetId, @RequestParam long referringPageId) {
+        final User user = userService.getAuthenticatedUser(); 
+        widgetStoreModelHelper(model, referringPageId, user);
         model.addAttribute(ModelKeys.WIDGET, widgetService.getWidget(widgetId));
-        model.addAttribute(ModelKeys.REFERRING_PAGE_ID, referringPageId);
-        final User user = userService.getAuthenticatedUser();
         model.addAttribute(ModelKeys.WIDGET_STATISTICS, widgetService.getWidgetStatistics(widgetId, user.getEntityId()));
         model.addAttribute(ModelKeys.USER_PROFILE, user);
-        model.addAttribute(ModelKeys.TAGS, tagService.getAllTags());
         return ViewNames.WIDGET;
     }
 
@@ -133,13 +125,11 @@ public class WidgetStoreController {
                                    @RequestParam String searchTerm,
                                    @RequestParam(required = false, defaultValue = "0") int offset) {
         User user = userService.getAuthenticatedUser();
+        widgetStoreModelHelper(model, referringPageId, user);
         model.addAttribute(ModelKeys.WIDGETS,
                 widgetService.getPublishedWidgetsByFreeTextSearch(searchTerm, offset, getPageSize()));
-        model.addAttribute(ModelKeys.REFERRING_PAGE_ID, referringPageId);
         model.addAttribute(ModelKeys.SEARCH_TERM, searchTerm);
         model.addAttribute(ModelKeys.OFFSET, offset);
-        model.addAttribute(ModelKeys.WIDGETS_STATISTICS, widgetService.getAllWidgetStatistics(user.getEntityId()));
-        model.addAttribute(ModelKeys.TAGS, tagService.getAllTags());
        return ViewNames.STORE;
     }
 
@@ -157,15 +147,26 @@ public class WidgetStoreController {
                                    @RequestParam String keyword,
                                    @RequestParam(required = false, defaultValue = "0") int offset) {
         User user = userService.getAuthenticatedUser();
+        widgetStoreModelHelper(model, referringPageId, user);
         model.addAttribute(ModelKeys.WIDGETS,
                 widgetService.getWidgetsByTag(keyword, offset, getPageSize()));
-         model.addAttribute(ModelKeys.REFERRING_PAGE_ID, referringPageId);
         model.addAttribute(ModelKeys.OFFSET, offset);
-        model.addAttribute(ModelKeys.WIDGETS_STATISTICS, widgetService.getAllWidgetStatistics(user.getEntityId()));
-        model.addAttribute(ModelKeys.TAGS, tagService.getAllTags());
         model.addAttribute(ModelKeys.SELECTED_TAG, keyword);
         return ViewNames.STORE;
     }
+    
+    @RequestMapping(method = RequestMethod.GET, value = "category")
+    public String viewCategoryResult(@RequestParam(required = true) long referringPageId,
+                                     @RequestParam(required = true) long categoryId,
+                                     @RequestParam(required = false, defaultValue = "0") int offset,
+                                     Model model){
+        User authenticatedUser = userService.getAuthenticatedUser();
+        widgetStoreModelHelper(model, referringPageId, authenticatedUser);
+        model.addAttribute(ModelKeys.WIDGETS, widgetService.getWidgetsByCategory(categoryId, offset,getPageSize()));
+        model.addAttribute(ModelKeys.OFFSET, offset);
+        model.addAttribute(ModelKeys.SELECTED_CATEGORY, categoryId);
+        return ViewNames.STORE;
+    }
 
     /**
      * Shows the Add new Widget form
@@ -208,6 +209,20 @@ public class WidgetStoreController {
         return "redirect:/app/store/widget/" + storedWidget.getEntityId() + "?referringPageId=" + referringPageId;
     }
 
+    /**
+     * Add common model attributes to the model
+     *
+     * @param model             Model to add to
+     * @param referringPageId   Page to refer back to
+     * @param user              Current authenticated User
+     */
+    private void widgetStoreModelHelper(Model model, long referringPageId, User user){
+        model.addAttribute(ModelKeys.REFERRING_PAGE_ID, referringPageId);
+        model.addAttribute(ModelKeys.WIDGETS_STATISTICS, widgetService.getAllWidgetStatistics(user.getEntityId()));
+        model.addAttribute(ModelKeys.TAGS, tagService.getAllTags());
+        model.addAttribute(ModelKeys.CATEGORIES, categoryService.getAll());
+    }
+
     public int getPageSize() {
         final PortalPreference pageSizePref = preferenceService.getPreference(PortalPreferenceKeys.PAGE_SIZE);
         if (pageSizePref == null) {
@@ -219,6 +234,4 @@ public class WidgetStoreController {
             return MAXIMUM_WIDGETS_PER_PAGE;
         }
     }
-
-
 }

Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/util/ModelKeys.java Mon Jan 30 16:23:43 2012
@@ -43,7 +43,8 @@ public class ModelKeys {
     public static final String TOKENCHECK = "tokencheck";
     public static final String USER_MAP = "userMap";
     public static final String PORTAL_SETTINGS = "portalSettings";
-    public static final String TAGS="tags" ;
-    public static final String SELECTED_TAG="selectedTag" ;
+    public static final String TAGS = "tags";
+    public static final String SELECTED_TAG = "selectedTag";
     public static final String CATEGORIES = "categories";
+    public static final String SELECTED_CATEGORY = "selectedCategory";
 }

Modified: incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/controller/WidgetStoreControllerTest.java Mon Jan 30 16:23:43 2012
@@ -20,12 +20,15 @@
 package org.apache.rave.portal.web.controller;
 
 
+import org.apache.rave.portal.model.Category;
+import org.apache.rave.portal.model.Tag;
 import org.apache.rave.portal.model.User;
 import org.apache.rave.portal.model.Widget;
 import org.apache.rave.portal.model.util.SearchResult;
 import org.apache.rave.portal.model.util.WidgetStatistics;
 import org.apache.rave.portal.service.PortalPreferenceService;
 import org.apache.rave.portal.service.TagService;
+import org.apache.rave.portal.service.CategoryService;
 import org.apache.rave.portal.service.UserService;
 import org.apache.rave.portal.service.WidgetService;
 import org.apache.rave.portal.web.util.ModelKeys;
@@ -69,6 +72,7 @@ public class WidgetStoreControllerTest {
     private WidgetStoreController controller;
     private WidgetService widgetService;
     private TagService tagService;
+    private CategoryService categoryService;
     private User validUser;
     private WidgetStatistics widgetStatistics;
     private Map<Long, WidgetStatistics> allWidgetStatisticsMap;
@@ -84,6 +88,7 @@ public class WidgetStoreControllerTest {
 
         widgetService = createMock(WidgetService.class);
         tagService = createMock(TagService.class);
+        categoryService = createMock(CategoryService.class);
 
         UserService userService = createMock(UserService.class);
         expect(userService.getAuthenticatedUser()).andReturn(validUser);
@@ -95,7 +100,7 @@ public class WidgetStoreControllerTest {
 
         NewWidgetValidator widgetValidator = new NewWidgetValidator(widgetService);
         controller = new WidgetStoreController(widgetService, widgetValidator, userService,
-                preferenceService, tagService);
+                preferenceService, tagService, categoryService);
     }
 
     @Test
@@ -118,6 +123,7 @@ public class WidgetStoreControllerTest {
         assertThat((Long) model.asMap().get(ModelKeys.REFERRING_PAGE_ID), is(equalTo(REFERRER_ID)));
         assertThat(widgets, is(sameInstance(emptyResult.getResultSet())));
         assertThat(model.containsAttribute(ModelKeys.TAGS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.CATEGORIES), is(true));
 
     }
 
@@ -140,6 +146,7 @@ public class WidgetStoreControllerTest {
         assertThat((Long) model.asMap().get(ModelKeys.REFERRING_PAGE_ID), is(equalTo(REFERRER_ID)));
         assertThat(widgets, is(sameInstance(emptyResult.getResultSet())));
         assertThat(model.containsAttribute(ModelKeys.TAGS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.CATEGORIES), is(true));
 
     }
 
@@ -148,6 +155,9 @@ public class WidgetStoreControllerTest {
         Model model = new ExtendedModelMap();
         Widget w = new Widget(1L, "http://example.com/widget.xml");
 
+        expect(widgetService.getAllWidgetStatistics(validUser.getEntityId())).andReturn(allWidgetStatisticsMap);
+        expect(tagService.getAllTags()).andReturn(new ArrayList<Tag>());
+        expect(categoryService.getAll()).andReturn(new ArrayList<Category>());
         expect(widgetService.getWidget(WIDGET_ID)).andReturn(w);
         expect(widgetService.getWidgetStatistics(WIDGET_ID, validUser.getEntityId())).andReturn(widgetStatistics);
         replay(widgetService);
@@ -158,12 +168,42 @@ public class WidgetStoreControllerTest {
         assertThat(view, is(equalTo(ViewNames.WIDGET)));
         assertThat(model.containsAttribute(ModelKeys.WIDGET), is(true));
         assertThat(model.containsAttribute(ModelKeys.WIDGET_STATISTICS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.TAGS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.CATEGORIES), is(true));
+        assertThat(model.containsAttribute(ModelKeys.REFERRING_PAGE_ID), is(true));
         assertThat(((Widget) model.asMap().get(ModelKeys.WIDGET)), is(sameInstance(w)));
         assertNull(model.asMap().get("widgetRating"));
 
     }
 
     @Test
+    public void viewCategoryResult_valid() {
+        Model model = new ExtendedModelMap();
+        long categoryId = 1L;
+        int offset = 0;
+        int pageSize = 10;
+        SearchResult<Widget> searchResults = new SearchResult<Widget>(new ArrayList<Widget>(),0);
+        expect(widgetService.getAllWidgetStatistics(validUser.getEntityId())).andReturn(allWidgetStatisticsMap);
+        expect(tagService.getAllTags()).andReturn(new ArrayList<Tag>());
+        expect(categoryService.getAll()).andReturn(new ArrayList<Category>());
+        expect(widgetService.getWidgetsByCategory(categoryId, offset, pageSize)).andReturn(searchResults);
+        replay(widgetService, tagService, categoryService);
+
+        String view = controller.viewCategoryResult(REFERRER_ID, categoryId, offset, model);
+
+        verify(widgetService, tagService, categoryService);
+        assertThat(view, is(equalTo(ViewNames.STORE)));
+        assertThat(model.containsAttribute(ModelKeys.WIDGETS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.WIDGETS_STATISTICS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.TAGS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.CATEGORIES), is(true));
+        assertThat(model.containsAttribute(ModelKeys.REFERRING_PAGE_ID), is(true));
+        assertThat(model.containsAttribute(ModelKeys.OFFSET), is(true));
+        assertThat(model.containsAttribute(ModelKeys.SELECTED_CATEGORY), is(true));
+
+    }
+
+    @Test
     public void searchWidgets() {
         Model model = new ExtendedModelMap();
 
@@ -194,6 +234,7 @@ public class WidgetStoreControllerTest {
         assertEquals(offset, modelMap.get(ModelKeys.OFFSET));
         assertEquals(result, modelMap.get(ModelKeys.WIDGETS));
         assertThat(model.containsAttribute(ModelKeys.TAGS), is(true));
+        assertThat(model.containsAttribute(ModelKeys.CATEGORIES), is(true));
 
     }
 

Modified: incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties Mon Jan 30 16:23:43 2012
@@ -117,6 +117,7 @@ page.store.list.search.result.x.to.y=Sho
 page.store.list.widgets.mine=My Widgets
 page.store.list.widgets.all=All Widgets
 page.store.list.widgets.tag=By Tag:
+page.store.list.widgets.category=By Category:
 
 page.userprofile.title=Update user profile
 page.userprofile.button=Update profile

Modified: incubator/rave/trunk/rave-portal-resources/src/main/resources/messages_nl.properties
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/resources/messages_nl.properties?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/resources/messages_nl.properties (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/resources/messages_nl.properties Mon Jan 30 16:23:43 2012
@@ -126,6 +126,7 @@ page.store.list.search.result.x.to.y={0}
 page.store.list.widgets.mine=Mijn widgets
 page.store.list.widgets.all=Alle widgets
 page.store.list.widgets.tag= Door  Tag:
+page.store.list.widgets.category= Op categorie:
 
 page.userprofile.title=Update gebruikersprofiel
 page.userprofile.button=Update profiel

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/store.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/store.jsp?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/store.jsp (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/store.jsp Mon Jan 30 16:23:43 2012
@@ -73,22 +73,45 @@
                 </c:if>
             </p>
             <c:if test="${not empty tags}">
-                <fmt:message key="page.store.list.widgets.tag"/>
-                <select name="tagList" id="tagList" style="width:100px" >
-                    <option value="  "></option>
-                    <c:forEach var="tag" items="${tags}">
-                        <c:choose>
-                            <c:when test="${selectedTag==tag.keyword}">
-                                <option selected>
-                            </c:when>
-                            <c:otherwise>
-                                <option>
-                            </c:otherwise>
-                        </c:choose>
-                        <c:out value="${tag.keyword}"/>
-                        </option>
-                    </c:forEach>
-                </select>
+                <div>
+                    <fmt:message key="page.store.list.widgets.tag"/>
+                    <select name="tagList" id="tagList" style="min-width:100px" >
+                        <option value="  "></option>
+                        <c:forEach var="tag" items="${tags}">
+                            <c:choose>
+                                <c:when test="${selectedTag==tag.keyword}">
+                                    <option selected>
+                                </c:when>
+                                <c:otherwise>
+                                    <option>
+                                </c:otherwise>
+                            </c:choose>
+                            <c:out value="${tag.keyword}"/>
+                            </option>
+                        </c:forEach>
+                    </select>
+                </div>
+            </c:if>
+
+            <c:if test="${not empty categories}">
+                <div>
+                    <fmt:message key="page.store.list.widgets.category"/>
+                    <select name="categoryList" id="categoryList" style="min-width:100px" >
+                        <option value="  "></option>
+                        <c:forEach var="category" items="${categories}">
+                            <c:choose>
+                                <c:when test="${selectedCategory==category.entityId}">
+                                    <option value="${category.entityId}" selected>
+                                </c:when>
+                                <c:otherwise>
+                                    <option value="${category.entityId}">
+                                </c:otherwise>
+                            </c:choose>
+                            <c:out value="${category.text}"/>
+                            </option>
+                        </c:forEach>
+                    </select>
+                </div>
             </c:if>
         </fieldset>
     </form>
@@ -324,9 +347,6 @@
 <script>
     $(function () {
         rave.setContext("<spring:url value="/app/" />");
-        rave.store.init();
-        rave.store.initWidgetsTag('<c:out value="${referringPageId}"/>');
+        rave.store.init('<c:out value="${referringPageId}"/>');
     });
-
-
 </script>
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/widget.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/widget.jsp?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/widget.jsp (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/jsp/views/widget.jsp Mon Jan 30 16:23:43 2012
@@ -238,9 +238,7 @@
 <script>
     $(function () {
         rave.setContext("<spring:url value="/app/" />");
-        rave.store.init();
-        rave.store.initComments();
+        rave.store.init('<c:out value="${referringPageId}"/>');
         rave.store.initTags("<c:out value="${widget.entityId}"/>");
-
     });
 </script>
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css Mon Jan 30 16:23:43 2012
@@ -886,7 +886,7 @@ span.error, label.error {
 
 #errorStack {
     display: none;
-    width: 30%;
+    width: 90%;
     margin: auto;
 }
 

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_store.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_store.js?rev=1237759&r1=1237758&r2=1237759&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_store.js (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_store.js Mon Jan 30 16:23:43 2012
@@ -141,7 +141,7 @@ rave.store = rave.store || (function() {
                         window.location.reload();
                     }});
             });
-//    load the tag by widgetId
+        //    load the tag by widgetId
         rave.api.rest.getTags({ widgetId:widgetId,
             successCallback:function (data) {
                 var result = ($.map(data, function (tag) {
@@ -159,23 +159,43 @@ rave.store = rave.store || (function() {
     }
 
     function initWidgetsTag(referringPageId) {
-           // tag list box
-           $("#tagList").change(function() {
-               var selected = $("#tagList option:selected").text();
-               selected=$.trim(selected)
-               if (selected.length > 1) {
-                   document.location.href = rave.getContext() + "store/tag?keyword=" + selected
+        if (referringPageId != null){
+            // tag list box
+            $("#tagList").change(function() {
+                var selected = $("#tagList option:selected").text();
+                selected=$.trim(selected)
+                if (selected.length > 1) {
+                    document.location.href = rave.getContext() + "store/tag?keyword=" + selected
                            +"&referringPageId="+referringPageId;
-               }
-           });
+                }
+            });
+        }
+    }
 
-       }
+    function initWidgetsCategory(referringPageId) {
+        if (referringPageId != null){
+            // category list box
+            $("#categoryList").change(function() {
+                var selected = $("#categoryList option:selected").val();
+                selected = parseInt(selected);
+                if (!isNaN(selected)) {
+                   document.location.href = rave.getContext() + "store/category?categoryId=" + selected
+                           +"&referringPageId="+referringPageId;
+                }
+            });
+        }
+    }
+
+    function init(referringPageId){
+        initRatings();
+        initComments();
+        initWidgetsTag(referringPageId);
+        initWidgetsCategory(referringPageId);
+    }
 
     return {
-        init: initRatings,
-        initComments: initComments,
-        initTags: initTags,
-        initWidgetsTag:initWidgetsTag
-    };                             
+        init: init,
+        initTags: initTags
+    };
     
 }());
\ No newline at end of file