rave-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From carlu...@apache.org
Subject svn commit: r1166244 - in /incubator/rave/trunk/rave-portal/src: main/java/org/apache/rave/portal/service/ main/java/org/apache/rave/portal/service/impl/ main/java/org/apache/rave/portal/web/api/rest/ main/java/org/apache/rave/provider/opensocial/web/r...
Date Wed, 07 Sep 2011 16:00:58 GMT
Author: carlucci
Date: Wed Sep  7 16:00:56 2011
New Revision: 1166244

URL: http://svn.apache.org/viewvc?rev=1166244&view=rev
Log:
RAVE-54: persisted minimization of widgets

Modified:
    incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/RegionWidgetService.java
    incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultRegionWidgetService.java
    incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
    incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java
    incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/home.jsp
    incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css
    incubator/rave/trunk/rave-portal/src/main/webapp/script/rave.js
    incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_api.js
    incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_opensocial.js
    incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/RegionWidgetServiceTest.java
    incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/api/rest/RegionWidgetApiTest.java
    incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
    incubator/rave/trunk/rave-portal/src/test/javascript/raveApiSpec.js
    incubator/rave/trunk/rave-portal/src/test/javascript/raveSpec.js

Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/RegionWidgetService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/RegionWidgetService.java?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/RegionWidgetService.java
(original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/RegionWidgetService.java
Wed Sep  7 16:00:56 2011
@@ -60,4 +60,13 @@ public interface RegionWidgetService {
      * @return The updated RegionWidgetPreference with all ID numbers populated.
      */
     RegionWidgetPreference saveRegionWidgetPreference(long regionWidgetId, RegionWidgetPreference
preference);
+    
+    /**
+     * Saves the collapsed state of the given regionWidgetId
+     * 
+     * @param regionWidgetId The ID of the RegionWidget to save the collapsed value for
+     * @param collapsed the collapsed state of the RegionWidget
+     * @return The updated RegionWidget with the new collapsed value
+     */
+    RegionWidget saveRegionWidgetCollapsedState(long regionWidgetId, boolean collapsed);
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultRegionWidgetService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultRegionWidgetService.java?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultRegionWidgetService.java
(original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/service/impl/DefaultRegionWidgetService.java
Wed Sep  7 16:00:56 2011
@@ -31,6 +31,7 @@ import org.springframework.stereotype.Se
 
 import java.util.Arrays;
 import java.util.List;
+import org.springframework.transaction.annotation.Transactional;
 
 @Service
 public class DefaultRegionWidgetService implements RegionWidgetService {
@@ -77,6 +78,14 @@ public class DefaultRegionWidgetService 
         return preference;
     }
 
+    @Override
+    @Transactional
+    public RegionWidget saveRegionWidgetCollapsedState(long regionWidgetId, boolean collapsed)
{
+        RegionWidget regionWidget = getValidRegionWidget(regionWidgetId);
+        regionWidget.setCollapsed(collapsed);
+        return saveRegionWidget(regionWidget);
+    }
+    
     private RegionWidget getValidRegionWidget(long regionWidgetId) {
         RegionWidget regionWidget = this.getRegionWidget(regionWidgetId);
         if (regionWidget == null) {

Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
(original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/portal/web/api/rest/RegionWidgetApi.java
Wed Sep  7 16:00:56 2011
@@ -30,6 +30,7 @@ import org.springframework.stereotype.Co
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
+import org.apache.rave.portal.model.RegionWidget;
 
 /**
  * Handler for all services exposed under the /api/regionWidgets path.
@@ -76,4 +77,23 @@ public class RegionWidgetApi {
 
         return regionWidgetService.saveRegionWidgetPreference(regionWidgetId, regionWidgetPreference);
     }
+        
+    /**
+     * REST call to update the collapsed value of a RegionWidget
+     * 
+     * @param regionWidgetId the ID of the RegionWidget to update
+     * @param collapsed boolean representing the new collapse state
+     * @return the updated RegionWidget object
+     */
+    @ResponseBody
+    @RequestMapping(value = "/{regionWidgetId}/collapsed", method = RequestMethod.PUT)
+    public RegionWidget updateRegionWidgetCollapsedStatus(@PathVariable long regionWidgetId,
+                                                          @RequestBody Boolean collapsed)
{
+        if (logger.isDebugEnabled()) {
+            logger.debug("POST received to update regionWidget " +
+                    regionWidgetId + ": " + collapsed);
+        }
+        
+        return regionWidgetService.saveRegionWidgetCollapsedState(regionWidgetId, collapsed);
             
+    }
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java
(original)
+++ incubator/rave/trunk/rave-portal/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java
Wed Sep  7 16:00:56 2011
@@ -59,7 +59,8 @@ public class OpenSocialWidgetRenderer im
             " widgetUrl: '%3$s', " +
             " securityToken: '%4$s', " +
             " metadata: %5$s," +
-            " userPrefs: %6$s});";
+            " userPrefs: %6$s," +
+            " collapsed: %7$s});";
 
     @Override
     public String getSupportedContext() {
@@ -92,6 +93,6 @@ public class OpenSocialWidgetRenderer im
 
         return String.format(IFRAME_MARKUP, Constants.WIDGET_TYPE, item.getId(), item.getWidget().getUrl(),
                 securityTokenService.getEncryptedSecurityToken(item),
-                openSocialService.getGadgetMetadata(item.getWidget().getUrl()), userPrefs.toString());
+                openSocialService.getGadgetMetadata(item.getWidget().getUrl()), userPrefs.toString(),
item.isCollapsed());
     }
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/home.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/home.jsp?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/home.jsp (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/WEB-INF/views/home.jsp Wed Sep  7 16:00:56
2011
@@ -87,9 +87,10 @@
     <div id="pageContent">
         <c:forEach var="region" items="${page.regions}">
             <div class="region" id="region-${region.id}-id">
-                <c:forEach var="regionWidget" items="${region.regionWidgets}">
-                    <div class="widget-wrapper" id="widget-${regionWidget.id}-wrapper">
+                <c:forEach var="regionWidget" items="${region.regionWidgets}">    
                                                
+                   <div class="widget-wrapper" id="widget-${regionWidget.id}-wrapper">
                         <div class="widget-title-bar">
+                            <span id="widget-${regionWidget.id}-collapse" class="widget-toolbar-toggle-collapse"
title="Collapse/Restore Widget"></span>
                             <span id="widget-${regionWidget.id}-title"><c:out value="${regionWidget.widget.title}"/></span>
                             <!-- These are toolbar buttons -->
                             <div id="widget-${regionWidget.id}-toolbar" style="float:right;">

Modified: incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/css/default.css Wed Sep  7 16:00:56 2011
@@ -442,6 +442,12 @@ button.widget-toolbar-btn-prefs {
     display: none;
 }
 
+.widget-toolbar-toggle-collapse {
+    display: inline-block;
+    vertical-align: middle;    
+    cursor: pointer;
+}
+
 /* Form fields */
 
 fieldset{

Modified: incubator/rave/trunk/rave-portal/src/main/webapp/script/rave.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/script/rave.js?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/script/rave.js (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/script/rave.js Wed Sep  7 16:00:56 2011
@@ -54,6 +54,14 @@ var rave = rave || (function() {
         var WIDGET_PREFS_INPUT_CLASS = "widget-prefs-input";
         var WIDGET_PREFS_INPUT_REQUIRED_CLASS = "widget-prefs-input-required";
         var WIDGET_PREFS_INPUT_FAILED_VALIDATION = "widget-prefs-input-failed-validation";
+        
+        var WIDGET_ICON_BASE_CLASS = "ui-icon";
+        var WIDGET_BTN_MAXIMIZE_CLASS = "ui-icon-arrow-4-diag";
+        var WIDGET_BTN_MINIMIZE_CLASS = "ui-icon-arrowthick-1-sw";
+        var WIDGET_BTN_DELETE_CLASS = "ui-icon-close";
+        var WIDGET_BTN_EDIT_PREFS_CLASS = "ui-icon-pencil";
+        var WIDGET_TOGGLE_DISPLAY_COLLAPSED = "ui-icon-triangle-1-e";
+        var WIDGET_TOGGLE_DISPLAY_NORMAL = "ui-icon-triangle-1-s";             
 
         function WIDGET_PREFS_EDIT_BUTTON(regionWidgetId) {
             return "widget-" + regionWidgetId + "-prefs";
@@ -91,7 +99,7 @@ var rave = rave || (function() {
                         start: dragStart, // event listener for drag start
                         stop : dragStop // event listener for drag stop
             });
-            initGadgetUI();
+            initWidgetUI();
         }
 
         function dragStart(event, ui) {
@@ -129,10 +137,10 @@ var rave = rave || (function() {
         /**
          * Takes care of the UI part of the widget rendering. Depends heavily on the HTML
structure
          */
-        function initGadgetUI() {
+        function initWidgetUI() {
             $(".widget-wrapper").each(function(){
                 var widgetId = extractObjectIdFromElementId($(this).attr("id"));
-                styleGadgetButtons(widgetId);
+                styleWidgetButtons(widgetId);
             });
         }
 
@@ -140,24 +148,74 @@ var rave = rave || (function() {
             addOverlay($("#pageContent"));
             $(".region" ).sortable( "option", "disabled", true );
             $("#widget-" + args.data.id + "-wrapper").removeClass("widget-wrapper").addClass("widget-wrapper-canvas");
-            $("#widget-" + args.data.id + "-max").click({id:args.data.id}, minimizeAction);
+            
+            // changes to 'max' button:
+            // 1) clear out the previous max button click event and attach a new one
+            // 2) change the image
+            var $maxButton =  $("#widget-" + args.data.id + "-max");
+            $maxButton.unbind("click");
+            $maxButton.click({id:args.data.id}, minimizeAction);
+            $maxButton.button("option", "icons", {primary:WIDGET_BTN_MINIMIZE_CLASS});
+            
+            // hide the collapse/restore toggle icon in canvas mode
+            $("#widget-" + args.data.id + "-collapse").hide();
             var widget = getWidgetById(args.data.id);
-            if(typeof widget != "undefined" && typeof widget.maximize == "function")
{
+            if(typeof widget != "undefined" && isFunction(widget.maximize)) {
                 widget.maximize();
             }
-
         }
 
         function minimizeAction(args) {
             $(".dnd-overlay").remove();
             $(".region" ).sortable( "option", "disabled", false );
             $("#widget-" + args.data.id + "-wrapper").removeClass("widget-wrapper-canvas").addClass("widget-wrapper");
-            $("#widget-" + args.data.id + "-max").click({id:args.data.id}, maximizeAction);
+            
+            // changes to 'max' button:
+            // 1) clear out the previous max button click event and attach a new one
+            // 2) change the image
+            var $maxButton =  $("#widget-" + args.data.id + "-max");
+            $maxButton.unbind("click");
+            $maxButton.click({id:args.data.id}, maximizeAction);            
+            $maxButton.button("option", "icons", {primary:WIDGET_BTN_MAXIMIZE_CLASS});
+                                              
+            // re-show the collapse/restore toggle icon
+            $("#widget-" + args.data.id + "-collapse").show();
             var widget = getWidgetById(args.data.id);
-            if(typeof widget != "undefined" && typeof widget.minimize == "function")
{
-                widget.minimize();
+            // if the widget is collapsed execute the collapse function
+            // otherwise execute the minimize function
+            if(typeof widget != "undefined"){
+                if (widget.collapsed && isFunction(widget.collapse)) {
+                    widget.collapse();
+                } else if (isFunction(widget.minimize)) {
+                    widget.minimize();
+                }
             }
         }
+      
+        function toggleCollapseAction(args) {     
+            var regionWidgetId = args.data.id;
+            var widget = getWidgetById(regionWidgetId);    
+            // toggle the collapse state of the widget
+            var newCollapsedValue = !widget.collapsed;
+            var functionArgs = {"regionWidgetId": regionWidgetId, "collapsed": newCollapsedValue};
+            
+            // if this type of widget has a collapse or restore callback invoke it upon
+            // successfull persistence
+            if(typeof widget != "undefined") {                
+                // if this is a collapse action, and the widget has a collapse implementation
function,
+                // attach it as a callback function
+                if (newCollapsedValue && isFunction(widget.collapse)) {
+                    functionArgs.successCallback = widget.collapse;                 
+                } 
+                // if this is a restore action, and the widget has a restore implementation
function,
+                // attach it as a callback function
+                else if (!newCollapsedValue && isFunction(widget.restore)) {
+                    functionArgs.successCallback = widget.restore;                 
+                }
+            }
+            
+            rave.api.rest.saveWidgetCollapsedState(functionArgs);           
+        }      
 
         function deleteAction(args) {
             if (confirm("Are you sure you want to remove this widget from your page")) {
@@ -319,7 +377,7 @@ var rave = rave || (function() {
             // are the only inputs that could potentially contain empty data
             prefsElement.find("*").filter(":input").each(function(index, element) {
                 switch (element.type) {
-                    case "text": 
+                    case "text":
                         if (!validatePrefInput(element)) {
                             hasValidationErrors = true;
                             $(element).addClass(WIDGET_PREFS_INPUT_FAILED_VALIDATION);
@@ -360,7 +418,7 @@ var rave = rave || (function() {
                 // focus on the first input that has validation errors
                 prefsElement.find("." + WIDGET_PREFS_INPUT_FAILED_VALIDATION).first().focus();

             } else {
-                if(typeof regionWidget.savePreferences == "function") {
+                if(isFunction(regionWidget.savePreferences)) {
                     regionWidget.savePreferences(updatedPrefs);
                 }
 
@@ -397,31 +455,66 @@ var rave = rave || (function() {
          * Applies styling to the several buttons in the widget toolbar
          * @param widgetId identifier of the region widget
          */
-        function styleGadgetButtons(widgetId) {
+        function styleWidgetButtons(widgetId) {
+            var widget = rave.getWidgetById(widgetId);
+            
+            // init the maximize button
             $("#widget-" + widgetId + "-max").button({
                 text: false,
                 icons: {
-                    primary: "ui-icon-arrow-4-diag"
+                    primary: WIDGET_BTN_MAXIMIZE_CLASS
                 }
             }).click({id: widgetId}, maximizeAction);
 
+            // init the delete button
             $("#widget-" + widgetId + "-remove").button({
                 text: false,
                 icons: {
-                    primary: "ui-icon-close"
+                    primary: WIDGET_BTN_DELETE_CLASS
                 }
             }).click({id: widgetId}, deleteAction);
 
+            // init the edit preferences button
             $("#" + WIDGET_PREFS_EDIT_BUTTON(widgetId)).button({
                 text: false,
                 icons: {
-                    primary: "ui-icon-pencil"
+                    primary: WIDGET_BTN_EDIT_PREFS_CLASS
                 }
             }).click({id: widgetId}, editPrefsAction);
-        }
+                       
+            // init the collapse/restore toggle
+            // conditionally style the icon and setup the event handlers
+            var $toggleCollapseIcon = $("#widget-" + widgetId + "-collapse");
+            $toggleCollapseIcon.hide();
+            $toggleCollapseIcon.addClass(WIDGET_ICON_BASE_CLASS);
+            $toggleCollapseIcon.addClass((widget.collapsed) ? WIDGET_TOGGLE_DISPLAY_COLLAPSED
: WIDGET_TOGGLE_DISPLAY_NORMAL);                        
+            $toggleCollapseIcon
+                .click({id: widgetId}, toggleCollapseAction)
+                .mousedown(function(event) {
+                    // don't allow drag and drop when this item is clicked
+                    event.stopPropagation();
+                });       
+            $toggleCollapseIcon.show();
+        }
+                
+        /**
+         * Toggles the display of the widget collapse/restore icon.
+         * @param widgetId the widgetId of the rendered widget to toggle the icon for
+         */
+        function toggleCollapseWidgetIcon(widgetId) {
+            var $toggleIcon = $("#widget-" + widgetId + "-collapse");
+            if ($toggleIcon.hasClass(WIDGET_TOGGLE_DISPLAY_COLLAPSED)) {
+                $toggleIcon.removeClass(WIDGET_TOGGLE_DISPLAY_COLLAPSED);
+                $toggleIcon.addClass(WIDGET_TOGGLE_DISPLAY_NORMAL);
+            } else {
+                $toggleIcon.removeClass(WIDGET_TOGGLE_DISPLAY_NORMAL);
+                $toggleIcon.addClass(WIDGET_TOGGLE_DISPLAY_COLLAPSED);
+            }
+        }   
 
         return {
-          init : init
+          init : init,          
+          toggleCollapseWidgetIcon: toggleCollapseWidgetIcon
         };
 
     })();
@@ -503,6 +596,15 @@ var rave = rave || (function() {
         var fragment = (pageId != null) ? ("/" + pageId) : "";
         window.location.href = rave.getContext() + "page/view" + fragment;      
     }
+    
+    /**
+     * Utility function to determine if a javascript object is a function
+     * @param obj the object to check
+     * @return true if object is a function, false otherwise
+     */ 
+    function isFunction(obj) {       
+        return (typeof obj == "function");
+    }
 
     /**
      * Public API
@@ -586,6 +688,21 @@ var rave = rave || (function() {
          * 
          * @param pageId the pageId to view, or if null, the user's default page
          */
-        viewPage: viewPage
+        viewPage: viewPage,
+        
+        /**
+         * Toggles the collapse/restore icon of the rendered widget
+         * 
+         * @param widgetId the widgetId of the rendered widget to toggle
+         */
+        toggleCollapseWidgetIcon: ui.toggleCollapseWidgetIcon,
+        
+        /***
+         * Utility function to determine if a javascript object is a function or not
+         * 
+         * @param obj the object to check
+         * @return true if obj is a function, false otherwise
+         */
+        isFunction: isFunction
     }
 })();

Modified: incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_api.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_api.js?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_api.js (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_api.js Wed Sep  7 16:00:56
2011
@@ -67,6 +67,31 @@ rave.api = rave.api || (function() {
             });
         }
         
+        function saveWidgetCollapsedState(args) {
+            $.ajax({
+                type: 'PUT',
+                url: rave.getContext() + path + "regionWidgets/" + args.regionWidgetId +
"/collapsed",
+                data: JSON.stringify(args.collapsed),  
+                contentType: 'application/json',
+                dataType: 'json',
+                success: function(result) {
+                    // update the in-memory widget with the new collapsed status
+                    rave.getWidgetById(result.id).collapsed = result.collapsed;
+                    
+                    // toggle the collapse/restore icon
+                    rave.toggleCollapseWidgetIcon(result.id);
+                    
+                    // if the widget has supplied a collapse or restore 
+                    // callback function, invoke it so each widget provider
+                    // can handle the collapse / restore action independently
+                    if (typeof args.successCallback == 'function') {
+                        args.successCallback();
+                    }
+                },
+                error: handleError
+            });                        
+        }
+        
         function deletePage(args) {
             $.ajax({
                 type: 'DELETE',
@@ -83,6 +108,7 @@ rave.api = rave.api || (function() {
         return {
             saveWidgetPreferences : saveWidgetPreferences,
             saveWidgetPreference : saveWidgetPreference,
+            saveWidgetCollapsedState : saveWidgetCollapsedState,
             deletePage : deletePage
         };
     })();

Modified: incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_opensocial.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_opensocial.js?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_opensocial.js (original)
+++ incubator/rave/trunk/rave-portal/src/main/webapp/script/rave_opensocial.js Wed Sep  7
16:00:56 2011
@@ -115,13 +115,25 @@ rave.opensocial = rave.opensocial || (fu
     function renderNewGadget(gadget) {
         var widgetBodyElement = document.getElementById(["widget-", gadget.regionWidgetId,
"-body"].join(""));
         gadget.site = container.newGadgetSite(widgetBodyElement);
-        gadget.maximize = function() { renderGadgetView(rave.opensocial.VIEW_NAMES.CANVAS,
this); };
-        gadget.minimize = function() { renderGadgetView(rave.opensocial.VIEW_NAMES.HOME,
  this); };
+        gadget.maximize = function() { 
+            // always display the gadget in canvas view even if it currently collapsed
+            renderGadgetView(rave.opensocial.VIEW_NAMES.CANVAS, this); 
+        };
+        gadget.minimize = function() { 
+            renderGadgetViewIfNotCollapsed(rave.opensocial.VIEW_NAMES.HOME, this);      
      
+        };
+        gadget.collapse = function() { 
+            // hide the iframe of the gadget via css
+            $(getGadgetIframeByWidgetId(this.regionWidgetId)).hide();            
+        };
+        gadget.restore = function() {
+             renderGadgetView(rave.opensocial.VIEW_NAMES.HOME, rave.getWidgetById(this.regionWidgetId));
+        };
         gadget.savePreferences = function(userPrefs) {
             this.userPrefs = userPrefs;
             rave.api.rest.saveWidgetPreferences({regionWidgetId: this.regionWidgetId, userPrefs:
userPrefs});
-            // re-render the gadget in the same view          
-            renderGadgetView(rave.opensocial.getCurrentView(this.regionWidgetId), this);

+            // re-render the gadget in the same view if the gadget is not collapsed
+            renderGadgetViewIfNotCollapsed(rave.opensocial.getCurrentView(this.regionWidgetId),
this);             
         };
         
         // if the gadget has prefences to edit, display the edit prefs button in the gadget
chrome
@@ -129,7 +141,20 @@ rave.opensocial = rave.opensocial || (fu
             $("#widget-" + gadget.regionWidgetId + "-prefs").show();
         }
         
-        renderGadgetView(rave.opensocial.VIEW_NAMES.HOME, gadget);
+        // if the gadget is not collapsed, render it
+        renderGadgetViewIfNotCollapsed(rave.opensocial.VIEW_NAMES.HOME, gadget);        
+    }
+    
+    /**
+     * Utility function to render a gadget in the supplied view if the gadget's 
+     * collapsed attribute is false
+     * @param view the OpenSocial view to render
+     * @param gadget the OpenSocial gadget to render
+     */ 
+    function renderGadgetViewIfNotCollapsed(view, gadget) {
+        if (!gadget.collapsed) {
+            renderGadgetView(view, gadget);
+        }
     }
 
     /**
@@ -153,6 +178,21 @@ rave.opensocial = rave.opensocial || (fu
     }
 
     /**
+     * Returns the Common Container activeGadgetHolder object for the given widgetId
+     * @param widgetId the widgetId
+     */ 
+    function getActiveGadgetHolderByWidgetId(widgetId) {
+        return rave.getWidgetById(widgetId).site.getActiveGadgetHolder();     
+    }
+
+    /**
+     * Returns the iframe element of the gadget for the given widgetId
+     */
+    function getGadgetIframeByWidgetId(widgetId) {
+        return getActiveGadgetHolderByWidgetId(widgetId).getIframeElement();     
+    }        
+
+    /**
      * validates the metadata for the current gadget
      * @param metadata the metadata object to validate
      */
@@ -184,7 +224,10 @@ rave.opensocial = rave.opensocial || (fu
      * @param regionWidgetId of the gadget
      */
     function getCurrentView(regionWidgetId) {
-        return rave.getWidgetById(regionWidgetId).site.getActiveGadgetHolder().getView();
+        // the active gadget holder will be null if the gadget is collapsed
+        // as it won't be rendered on the page
+        var activeGadgetHolder = getActiveGadgetHolderByWidgetId(regionWidgetId);
+        return (activeGadgetHolder == null) ? null : activeGadgetHolder.getView();
     }
 
     /*

Modified: incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/RegionWidgetServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/RegionWidgetServiceTest.java?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/RegionWidgetServiceTest.java
(original)
+++ incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/service/RegionWidgetServiceTest.java
Wed Sep  7 16:00:56 2011
@@ -24,7 +24,7 @@ import org.apache.rave.portal.model.Regi
 import org.apache.rave.portal.model.RegionWidgetPreference;
 import org.apache.rave.portal.repository.RegionWidgetRepository;
 import org.apache.rave.portal.service.impl.DefaultRegionWidgetService;
-import org.hamcrest.CoreMatchers;
+import static org.hamcrest.CoreMatchers.*;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -57,7 +57,7 @@ public class RegionWidgetServiceTest {
         expect(regionWidgetRepository.get(VALID_REGION_WIDGET_ID)).andReturn(VALID_REGION_WIDGET);
         replay(regionWidgetRepository);
 
-        assertThat(regionWidgetService.getRegionWidget(VALID_REGION_WIDGET_ID), CoreMatchers.sameInstance(VALID_REGION_WIDGET));
+        assertThat(regionWidgetService.getRegionWidget(VALID_REGION_WIDGET_ID), sameInstance(VALID_REGION_WIDGET));
     }
 
     @Test
@@ -65,7 +65,7 @@ public class RegionWidgetServiceTest {
         expect(regionWidgetRepository.get(INVALID_REGION_WIDGET_ID)).andReturn(null);
         replay(regionWidgetRepository);
 
-        assertThat(regionWidgetService.getRegionWidget(INVALID_REGION_WIDGET_ID), CoreMatchers.<Object>nullValue());
+        assertThat(regionWidgetService.getRegionWidget(INVALID_REGION_WIDGET_ID), is(nullValue()));
     }
 
     @Test
@@ -75,7 +75,7 @@ public class RegionWidgetServiceTest {
         expect(regionWidgetRepository.save(VALID_REGION_WIDGET)).andReturn(VALID_REGION_WIDGET);
         replay(regionWidgetRepository);
 
-        assertThat(regionWidgetService.saveRegionWidget(VALID_REGION_WIDGET), CoreMatchers.sameInstance(VALID_REGION_WIDGET));
+        assertThat(regionWidgetService.saveRegionWidget(VALID_REGION_WIDGET), sameInstance(VALID_REGION_WIDGET));
     }
 
     @Test
@@ -116,7 +116,30 @@ public class RegionWidgetServiceTest {
         assertTrue(preferenceCollectionsMatch(existingPreferences, VALID_REGION_WIDGET.getPreferences()));
         assertTrue(preferencesHaveValidRegionWidgetId(VALID_REGION_WIDGET.getPreferences()));
     }
+        
+    @Test
+    public void saveRegionWidgetCollapsedState() {
+        final boolean COLLAPSED = true;
+        RegionWidget regionWidget = new RegionWidget(VALID_REGION_WIDGET_ID);
+        
+        expect(regionWidgetRepository.get(VALID_REGION_WIDGET_ID)).andReturn(regionWidget);
               
+        regionWidget.setCollapsed(COLLAPSED);
+        expect(regionWidgetRepository.save(regionWidget)).andReturn(regionWidget);
+        replay(regionWidgetRepository);
+
+        assertThat(regionWidgetService.saveRegionWidgetCollapsedState(VALID_REGION_WIDGET_ID,
COLLAPSED).isCollapsed(), is(COLLAPSED));
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void saveRegionWidgetCollapsedState_invalidWidgetId() {
+        final boolean COLLAPSED = true;
+      
+        expect(regionWidgetRepository.get(INVALID_REGION_WIDGET_ID)).andReturn(null);  
+        replay(regionWidgetRepository);
 
+        regionWidgetService.saveRegionWidgetCollapsedState(INVALID_REGION_WIDGET_ID, COLLAPSED);
+    }    
+    
     private boolean preferencesHaveValidRegionWidgetId(List<RegionWidgetPreference>
savedPreferences) {
         for (RegionWidgetPreference savedPreference : savedPreferences) {
             if (!savedPreference.getRegionWidgetId().equals(VALID_REGION_WIDGET_ID)) {

Modified: incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/api/rest/RegionWidgetApiTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/api/rest/RegionWidgetApiTest.java?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/api/rest/RegionWidgetApiTest.java
(original)
+++ incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/portal/web/api/rest/RegionWidgetApiTest.java
Wed Sep  7 16:00:56 2011
@@ -19,10 +19,11 @@
 
 package org.apache.rave.portal.web.api.rest;
 
+import org.apache.rave.portal.model.RegionWidget;
 import org.apache.rave.portal.model.RegionWidgetPreference;
 import org.apache.rave.portal.service.RegionWidgetService;
 import org.apache.rave.portal.web.model.RegionWidgetPreferenceListWrapper;
-import org.hamcrest.CoreMatchers;
+import static org.hamcrest.CoreMatchers.*;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -61,7 +62,7 @@ public class RegionWidgetApiTest {
                 LIST_WRAPPER);
 
         verify(regionWidgetService);
-        assertThat(result.getPreferences(), CoreMatchers.sameInstance(LIST_WRAPPER.getPreferences()));
+        assertThat(result.getPreferences(), sameInstance(LIST_WRAPPER.getPreferences()));
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -89,7 +90,7 @@ public class RegionWidgetApiTest {
                 VALID_PREFERENCE_NAME, PREFERENCE);
 
         verify(regionWidgetService);
-        assertThat(result, CoreMatchers.sameInstance(PREFERENCE));
+        assertThat(result, sameInstance(PREFERENCE));
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -111,4 +112,19 @@ public class RegionWidgetApiTest {
 
         regionWidgetApi.createOrReplaceRegionWidgetPreference(INVALID_REGION_WIDGET_ID, VALID_PREFERENCE_NAME,
PREFERENCE);
     }
+        
+    @Test
+    public void updateRegionWidgetCollapsedStatus() {
+        final boolean COLLAPSED = true;       
+        
+        RegionWidget expectedRegionWidget = new RegionWidget(VALID_REGION_WIDGET_ID);
+        expectedRegionWidget.setCollapsed(COLLAPSED);
+
+        expect(regionWidgetService.saveRegionWidgetCollapsedState(VALID_REGION_WIDGET_ID,
COLLAPSED)).andReturn(expectedRegionWidget); 
+        replay(regionWidgetService);
+        RegionWidget result = regionWidgetApi.updateRegionWidgetCollapsedStatus(VALID_REGION_WIDGET_ID,
COLLAPSED);
+        verify(regionWidgetService);
+        
+        assertThat(result, sameInstance(expectedRegionWidget));
+    }
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
(original)
+++ incubator/rave/trunk/rave-portal/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
Wed Sep  7 16:00:56 2011
@@ -47,6 +47,7 @@ public class OpenSocialWidgetRendererTes
     private static final String VALID_GADGET_URL = "http://www.example.com/gadget.xml";
     private static final String VALID_METADATA = "metadata";
     private static final String VALID_SECURITY_TOKEN = "securityToken";
+    private static final boolean VALID_COLLAPSED = true;
 
     @Before
     public void setup() {
@@ -71,9 +72,11 @@ public class OpenSocialWidgetRendererTes
         w.setUrl(VALID_GADGET_URL);
         RegionWidget rw = new RegionWidget();
         rw.setId(1L);
+        rw.setCollapsed(VALID_COLLAPSED);
         rw.setWidget(w);
         rw.setPreferences(Arrays.asList(new RegionWidgetPreference(1L, 1L, "color", "blue"),
-                new RegionWidgetPreference(2L, 1L, "speed", "fast")));
+                                        new RegionWidgetPreference(2L, 1L, "speed", "fast"),
+                                        new RegionWidgetPreference(3L, 1L, null, null)));
 
         expect(securityTokenService.getEncryptedSecurityToken(rw)).andReturn(VALID_SECURITY_TOKEN);
         replay(securityTokenService);
@@ -84,7 +87,7 @@ public class OpenSocialWidgetRendererTes
             result should look like:
 
             widgets.push({type: 'OpenSocial', regionWidgetId: 1, widgetUrl: 'http://www.example.com/gadget.xml',
-                securityToken: 'securityToken',  metadata: metadata, userPrefs: {"speed":"fast","color":"blue"}});
+                securityToken: 'securityToken',  metadata: metadata, userPrefs: {"speed":"fast","color":"blue"},
collapsed: true});
         */
 
         JSONObject jsonObject = new JSONObject(
@@ -97,6 +100,7 @@ public class OpenSocialWidgetRendererTes
         assertThat((String) jsonObject.get("metadata"), is(equalTo(VALID_METADATA)));
         assertThat((String) ((JSONObject) jsonObject.get("userPrefs")).get("color"), is(equalTo("blue")));
         assertThat((String) ((JSONObject) jsonObject.get("userPrefs")).get("speed"), is(equalTo("fast")));
+        assertThat((Boolean) jsonObject.get("collapsed"), is(equalTo(VALID_COLLAPSED)));
     }
 
     @Test
@@ -111,6 +115,7 @@ public class OpenSocialWidgetRendererTes
         assertThat(result.matches(".*type[ ]*:[ ]*'OpenSocial',.*"), is(true));
         assertThat(result.matches(".*widgetUrl[ ]*:[ ]*'null',.*"), is(true));
         assertThat(result.matches(".*metadata[ ]*:[ ]*null,.*"), is(true));
+        assertThat(result.matches(".*collapsed[ ]*:[ ]*false.*"), is(true));
     }
 
     @Test(expected = NotSupportedException.class)

Modified: incubator/rave/trunk/rave-portal/src/test/javascript/raveApiSpec.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/javascript/raveApiSpec.js?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/javascript/raveApiSpec.js (original)
+++ incubator/rave/trunk/rave-portal/src/test/javascript/raveApiSpec.js Wed Sep  7 16:00:56
2011
@@ -88,6 +88,32 @@ describe("Rave API", function() {
                 expect(callbackCalled).toBeTruthy();
             });
         });
+        
+        describe("saveWidgetCollapsedState", function() {
+            it("PUTs correct values to the REST service for saving the collapsed state of
a widget", function() {               
+                
+                $.ajax = function(args) {
+                    expect(args.url).toEqual("api/rest/regionWidgets/7/collapsed");     
              
+                    expect(JSON.parse(args.data)).toEqual(true);                        
          
+                    expect(typeof(callback)).toEqual("function");
+                    callback({error:false});
+                    return {
+                        error: function(a, b, c) {
+                        }
+                    }
+                };
+
+                var callbackCalled = false;
+                var callback = function() {
+                    callbackCalled = true
+                };
+                             
+                rave.api.rest.saveWidgetCollapsedState({regionWidgetId: 7, 
+                                                        collapsed: true,
+                                                        successCallback: callback});
+                expect(callbackCalled).toBeTruthy();
+            });
+        });        
                 
         describe("deletePage", function() {
             it("DELETEs the correct Page using the REST service", function() {

Modified: incubator/rave/trunk/rave-portal/src/test/javascript/raveSpec.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal/src/test/javascript/raveSpec.js?rev=1166244&r1=1166243&r2=1166244&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal/src/test/javascript/raveSpec.js (original)
+++ incubator/rave/trunk/rave-portal/src/test/javascript/raveSpec.js Wed Sep  7 16:00:56 2011
@@ -343,4 +343,101 @@ describe("Rave", function() {
     describe("Handle resize maximize event", function(){
 
     });
+    
+    describe("isFunction", function() {
+
+        it("returns true when the object is a function", function() {
+            var obj = function() { };
+            var result = rave.isFunction(obj);
+            expect(result).toEqual(true);
+        });
+        it("returns false when the object is a number", function() {
+            var obj = 1;
+            var result = rave.isFunction(obj);
+            expect(result).toEqual(false);
+        });        
+        it("returns false when the object is a string", function() {
+            var obj = "hello";
+            var result = rave.isFunction(obj);
+            expect(result).toEqual(false);
+        }); 
+        it("returns false when the object is an object", function() {
+            var obj = {"myattr" : "myvalue"};
+            var result = rave.isFunction(obj);
+            expect(result).toEqual(false);
+        }); 
+        it("returns false when the object is null", function() {
+            var obj = null;
+            var result = rave.isFunction(obj);
+            expect(result).toEqual(false);
+        }); 
+        it("returns false when the object is undefined", function() {
+            var obj;
+            var result = rave.isFunction(obj);
+            expect(result).toEqual(false);
+        }); 
+    });        
+    
+    describe("toggleCollapseWidgetIcon", function() {
+        //Creates a simple mock jquery object that mocks the functions used in this suite
+        function createMockJQuery() {
+            var expression;
+            var classMap = [];
+            
+            $ = function(expr) {
+
+                if (typeof expr != "undefined") {
+                    expression = expr;
+                }
+
+                return {
+                    expression : function () {
+                        return expression;
+                    },
+                    hasClass : function (className) {
+                        return classMap.indexOf(className) != -1;
+                    },
+                    addClass : function (className) {
+                        classMap.push(className);
+                    },
+                    removeClass: function(className) {                        
+                        var idx = classMap.indexOf(className); 
+                        if (idx != -1) {
+                            classMap.splice(idx, 1); 
+                        }
+                    }
+                }
+            };
+            
+        }
+
+        it("changes icon from normal to collapsed", function() {                        
         
+            createMockJQuery();
+            // setup the state so the widget display is "normal"           
+            $().addClass("ui-icon-triangle-1-e");
+           
+            var widgetId = 99;
+           
+            rave.toggleCollapseWidgetIcon(widgetId);
+           
+            expect($().expression()).toEqual("#widget-" + widgetId + "-collapse");      
     
+            expect($().hasClass("ui-icon-triangle-1-e")).toEqual(false);
+            expect($().hasClass("ui-icon-triangle-1-s")).toEqual(true);                 
                      
+        });
+        
+        it("changes icon from collapsed to normal", function() {                        
         
+            createMockJQuery();
+            // setup the state so the widget display is "normal"           
+            $().addClass("ui-icon-triangle-1-s");
+           
+            var widgetId = 99;
+           
+            rave.toggleCollapseWidgetIcon(widgetId);
+           
+            expect($().expression()).toEqual("#widget-" + widgetId + "-collapse");      
     
+            expect($().hasClass("ui-icon-triangle-1-s")).toEqual(false);
+            expect($().hasClass("ui-icon-triangle-1-e")).toEqual(true);                 
                      
+        });        
+       
+    });    
 });
\ No newline at end of file



Mime
View raw message