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 2011/10/10 20:38:09 UTC

svn commit: r1181124 [1/2] - 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/apac...

Author: carlucci
Date: Mon Oct 10 18:38:08 2011
New Revision: 1181124

URL: http://svn.apache.org/viewvc?rev=1181124&view=rev
Log:
RAVE-261: Move a widget to a different page

Patch applied which was supplied by Venkat Mahadevan

Modified:
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
    incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java
    incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/PageServiceTest.java
    incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rpc/PageApi.java
    incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rpc/PageApiTest.java
    incubator/rave/trunk/rave-portal-resources/src/main/resources/messages.properties
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/css/default.css
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_api.js
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_layout.js
    incubator/rave/trunk/rave-portal-resources/src/test/javascript/raveApiSpec.js

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/PageService.java Mon Oct 10 18:38:08 2011
@@ -21,9 +21,9 @@ package org.apache.rave.portal.service;
 import org.apache.rave.portal.model.Page;
 import org.apache.rave.portal.model.Region;
 import org.apache.rave.portal.model.RegionWidget;
+import org.apache.rave.portal.model.User;
 
 import java.util.List;
-import org.apache.rave.portal.model.User;
 
 public interface PageService {
     /**
@@ -97,6 +97,15 @@ public interface PageService {
     RegionWidget moveRegionWidget(long regionWidgetId, int newPosition, long toRegion, long fromRegion);
 
     /**
+     * Moves a RegionWidget from one page to another
+     *       
+     * @param regionWidgetId  the RegionWidget to move
+     * @param toPageId the new page to move the regionWidgetTo
+     * @return the updated RegionWidget object
+     */
+    RegionWidget moveRegionWidgetToPage(long regionWidgetId, long toPageId);    
+    
+    /**
      * Creates a new instance of a widget and adds it to the first position of the first region on the page
      * @param page_id the id of the page to add the widget to
      * @param widget_id the {@link org.apache.rave.portal.model.Widget} id to add
@@ -137,5 +146,5 @@ public interface PageService {
      * @param pageId the pageId of the page to move to the default position
      * @return the updated Page object containing its new render sequence
      */
-    Page movePageToDefault(long pageId);
+    Page movePageToDefault(long pageId);  
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/main/java/org/apache/rave/portal/service/impl/DefaultPageService.java Mon Oct 10 18:38:08 2011
@@ -130,6 +130,26 @@ public class DefaultPageService implemen
         target = regionRepository.save(target);
         return findRegionWidgetById(regionWidgetId, target.getRegionWidgets());
     }
+    
+    @Override
+    @Transactional
+    public RegionWidget moveRegionWidgetToPage(long regionWidgetId, long toPageId) {                
+        // Get the new page
+        Page toPage = getFromRepository(toPageId, pageRepository);
+        // Get the region widget
+        RegionWidget regionWidget = getFromRepository(regionWidgetId, regionWidgetRepository);
+        
+        // Move it to first position of the first region
+        Region moveToRegion = toPage.getRegions().get(0);
+        regionWidget.setRenderOrder(0);
+        regionWidget.setRegion(moveToRegion);
+        moveToRegion.getRegionWidgets().add(0, regionWidget);
+        // update the rendersequences of the widgets in this region
+        updateRenderSequences(moveToRegion.getRegionWidgets());
+        // persist it
+        regionRepository.save(moveToRegion);
+        return getFromRepository(regionWidgetId, regionWidgetRepository);        
+    }    
 
     @Override
     @Transactional
@@ -152,8 +172,8 @@ public class DefaultPageService implemen
     @Transactional
     public Page movePage(long pageId, long moveAfterPageId) {
         return doMovePage(pageId, moveAfterPageId);
-    }    
-    
+    }
+
     @Override
     @Transactional
     public Page movePageToDefault(long pageId) {    

Modified: incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/PageServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/PageServiceTest.java?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/PageServiceTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-core/src/test/java/org/apache/rave/portal/service/PageServiceTest.java Mon Oct 10 18:38:08 2011
@@ -58,6 +58,9 @@ public class PageServiceTest {
     private final String PAGE_LAYOUT_CODE = "layout1";
     private final long PAGE_ID = 1L;
     private final long INVALID_PAGE_ID = -1L;
+
+    final Long VALID_REGION_WIDGET_ID = 1L;
+    final Long INVALID_REGION_WIDGET_ID = 100L;
             
     private Region targetRegion;
     private Region originalRegion;
@@ -809,4 +812,59 @@ public class PageServiceTest {
         }
         return regions;
     }
+
+    @Test
+    public void moveRegionWidgetToPage_valid() {
+        final long WIDGET_ID = 1L;
+        final long CURRENT_PAGE_ID = 1L;
+        final long TO_PAGE_ID = 2L;
+
+        Page currentPageValue = new Page();
+        currentPageValue.setRegions(new ArrayList<Region>());
+        currentPageValue.getRegions().add(originalRegion);
+        currentPageValue.getRegions().add(targetRegion);
+
+        Page toPageValue = new Page();
+        toPageValue.setRegions(new ArrayList<Region>());
+        toPageValue.getRegions().add(originalRegion);
+        toPageValue.getRegions().add(targetRegion);
+
+        RegionWidget regionWidget = new RegionWidget(VALID_REGION_WIDGET_ID);
+
+        expect(pageRepository.get(TO_PAGE_ID)).andReturn(toPageValue);
+        expect(regionWidgetRepository.get(WIDGET_ID)).andReturn(regionWidget).times(2);
+
+        replay(pageRepository);
+        replay(regionWidgetRepository);
+
+        RegionWidget updatedRegionWidget = pageService.moveRegionWidgetToPage(VALID_REGION_WIDGET_ID, TO_PAGE_ID);
+
+        verify(pageRepository);
+        verify(regionWidgetRepository);
+        verifyPositions(0, regionWidget, true);
+
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void moveRegionWidgetToPage_invalidWidget() {
+        long WIDGET_ID = -1L;
+        final long CURRENT_PAGE_ID = 1L;
+        final long TO_PAGE_ID = 2L;
+
+        Page currentPageValue = new Page();
+        currentPageValue.setRegions(new ArrayList<Region>());
+        currentPageValue.getRegions().add(originalRegion);
+        currentPageValue.getRegions().add(targetRegion);
+
+        Page toPageValue = new Page();
+        toPageValue.setRegions(new ArrayList<Region>());
+        toPageValue.getRegions().add(originalRegion);
+        toPageValue.getRegions().add(targetRegion);
+
+        expect(pageRepository.get(CURRENT_PAGE_ID)).andReturn(currentPageValue);
+        expect(pageRepository.get(TO_PAGE_ID)).andReturn(toPageValue);
+        expect(regionWidgetRepository.get(WIDGET_ID)).andReturn(null);
+
+        pageService.moveRegionWidgetToPage(VALID_REGION_WIDGET_ID, TO_PAGE_ID);
+    }
 }

Modified: incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rpc/PageApi.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rpc/PageApi.java?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rpc/PageApi.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/main/java/org/apache/rave/portal/web/api/rpc/PageApi.java Mon Oct 10 18:38:08 2011
@@ -196,4 +196,24 @@ public class PageApi {
             }
         }.getResult();        
     }
+
+    /**
+     * Moves a region widget to a new page
+     *
+     * @param toPageId the pageId to move the region widget to
+     * @param regionWidgetId the regionWidgetId that needs to be moved
+     * @return an {@link RpcOperation} containing the updated RegionWidget or any
+     *         errors encountered.
+     */
+    @ResponseBody
+    @RequestMapping(method = RequestMethod.POST, value = "{toPageId}/moveWidget")
+    public RpcResult<RegionWidget> moveWidgetToPage(@PathVariable final long toPageId,
+                                                    @RequestParam(required=false) final long regionWidgetId) {
+        return new RpcOperation<RegionWidget>() {
+            @Override
+            public RegionWidget execute() {
+                return pageService.moveRegionWidgetToPage(regionWidgetId, toPageId);
+            }
+        }.getResult();
+    }
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rpc/PageApiTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rpc/PageApiTest.java?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rpc/PageApiTest.java (original)
+++ incubator/rave/trunk/rave-components/rave-web/src/test/java/org/apache/rave/portal/web/api/rpc/PageApiTest.java Mon Oct 10 18:38:08 2011
@@ -56,7 +56,7 @@ public class PageApiTest {
     }
 
     @Test
-    public void moveWidget_validParams() {
+    public void moveWidgetOnPage_validParams() {
         final long TO_REGION = 1;
         final long FROM_REGION = 2;
 
@@ -72,7 +72,7 @@ public class PageApiTest {
     }
 
     @Test
-    public void moveWidget_invalidParams() {
+    public void moveWidgetOnPage_invalidParams() {
         final long TO_REGION = -1;
         final long FROM_REGION = 2;
 
@@ -89,7 +89,7 @@ public class PageApiTest {
     }
 
     @Test
-    public void moveWidget_internalError() {
+    public void moveWidgetOnPage_internalError() {
         final long TO_REGION = 1;
         final long FROM_REGION = 2;
 
@@ -305,4 +305,45 @@ public class PageApiTest {
         assertThat(result.getErrorCode(), is(RpcResult.ErrorCode.NO_ERROR));
         assertThat(result.getErrorMessage(), is(nullValue()));
     }      
+    
+    @Test
+    public void moveWidgetToPage_validParams() {      
+        expect(pageService.moveRegionWidgetToPage(REGION_WIDGET_ID, PAGE_2_ID)).andReturn(new RegionWidget());
+        replay(pageService);
+        RpcResult<RegionWidget> result = pageApi.moveWidgetToPage(PAGE_2_ID, REGION_WIDGET_ID);
+        verify(pageService);
+        assertThat(result, is(notNullValue()));
+        assertThat(result.getResult(), is(notNullValue()));
+        assertThat(result.isError(), is(false));
+        assertThat(result.getErrorCode(), is(RpcResult.ErrorCode.NO_ERROR));
+        assertThat(result.getErrorMessage(), is(nullValue()));
+    }
+
+    @Test
+    public void moveWidgetToPage_invalidParams() {    
+        expect(pageService.moveRegionWidgetToPage(REGION_WIDGET_ID, PAGE_2_ID)).andThrow(new IllegalArgumentException(PARAM_ERROR_MESSAGE));
+        replay(pageService);
+
+        RpcResult<RegionWidget> result = pageApi.moveWidgetToPage(PAGE_2_ID, REGION_WIDGET_ID);
+        verify(pageService);
+        assertThat(result, is(notNullValue()));
+        assertThat(result.getResult(), is(nullValue()));
+        assertThat(result.isError(), is(true));
+        assertThat(result.getErrorCode(), is(RpcResult.ErrorCode.INVALID_PARAMS));
+        assertThat(result.getErrorMessage(), is(equalTo(PARAM_ERROR_MESSAGE)));
+    }
+
+    @Test
+    public void moveWidgetToPage_internalError() {
+        expect(pageService.moveRegionWidgetToPage(REGION_WIDGET_ID, PAGE_2_ID)).andThrow(new RuntimeException(INTERNAL_ERROR_MESSAGE));
+        replay(pageService);
+
+        RpcResult<RegionWidget> result = pageApi.moveWidgetToPage(PAGE_2_ID, REGION_WIDGET_ID);
+        verify(pageService);
+        assertThat(result, is(notNullValue()));
+        assertThat(result.getResult(), is(nullValue()));
+        assertThat(result.isError(), is(true));
+        assertThat(result.getErrorCode(), is(RpcResult.ErrorCode.INTERNAL_ERROR));
+        assertThat(result.getErrorMessage(), is(equalTo(INTERNAL_ERROR_MESSAGE)));
+    }  
 }

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=1181124&r1=1181123&r2=1181124&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 Oct 10 18:38:08 2011
@@ -1,144 +1,146 @@
-#
-# 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.
-#
-
-username.required=Username required
-username.invalid.length=Username must be at least 2 characters long
-username.invalid.pattern=Username must be at least 2 characters long and may only contain letters, numbers, \
-  _-+.@
-username.exists=Username already exists
-
-password.required=Password required
-password.invalid.length=Password must be at least 4 characters long
-
-confirmPassword.required=Confirm Password required
-confirmPassword.mismatch=Password mismatch
-
-email.required=Email required
-email.invalid=This is not a valid email address
-email.exists=This email address already exists for a user
-
-form.some.fields.required=Field marked with * are required
-form.all.fields.required=All fields are required.
-
-page.error.title=Rave has suffered a brief meltdown
-page.error.message=Please bear with us while we fetch some ice cubes.  In the meantime please try
-page.error.reload=reloading
-page.error.details=technical details
-
-page.general.back=Back to Rave
-page.general.addnewpage=Add a New Page
-page.general.confirmpassword=Confirm password:
-page.general.deletepage=Delete Page
-page.general.editpage=Edit Page
-page.general.email=Email address:
-page.general.logout=Logout
-page.general.movepage=Move Page
-page.general.movethispage=Move this page:
-page.general.movethispage.after=After {0}
-page.general.movethispage.tofirst=To First Tab (Set as Default)
-page.general.password=Password:
-page.general.screenshot=screenshot
-page.general.titlesuffix= - Rave
-page.general.thumbnail=thumbnail
-page.general.username=Username:
-
-page.general.addpage.title=Title
-page.general.addpage.layout.columns_1=One Column
-page.general.addpage.layout.columns_2=Two Columns
-page.general.addpage.layout.columns_2wn=Two Columns (wide/narrow)
-page.general.addpage.layout.columns_3=Three Columns
-page.general.addpage.layout.columns_3nwn=Three Columns (narrow/wide/narrow)
-page.general.addpage.layout.columns_4=Four Columns
-page.general.addpage.layout.columns_3nwn_1_bottom=Four Columns (narrow/wide/narrow/bottom)
-page.general.addpage.selectlayout=Select Page Layout:
-
-page.home.welcome=Hello {0}, welcome to Rave!
-
-page.login.title=Login
-page.login.createaccount=New User
-page.login.createaccount.label=Register:
-page.login.createaccount.button=Create New Account
-page.login.openid=OpenID Identity
-page.login.openid.button=Login with OpenID
-page.login.openid.fail=OpenID identification failed.
-page.login.openid.identifier=Identity:
-page.login.rememberme=Remember me
-page.login.usernamepassword=Username and Password
-page.login.usernamepassword.fail=The username or password is incorrect.
-page.login.usernamepassword.login=Login
-
-page.newaccount.title=New Account Application
-page.newaccount.button=Create Account
-
-page.store.title=Widget Store
-page.store.search=Search in widget store
-page.store.search.button=Search
-page.store.list.noresult=No widgets found
-page.store.list.result.x.to.y=Showing {0} - {1} of {2} widgets
-page.store.list.search.noresult=No widgets found for ''{0}''
-page.store.list.search.result.x.to.y=Showing {0} - {1} of {2} widgets that match ''{3}''
-
-page.userprofile.title=Update user profile
-page.userprofile.button=Update profile
-page.userprofile.openid.url=OpenID URL:
-
-page.widget.addToPage=Add to Page
-page.widget.backToStore=Back to Store
-page.widget.widgetPreview=Widget Preview
-
-page.addwidget.title=Add new widget
-page.addwidget.form.header=Widget
-page.addwidget.form.submit=Add widget
-page.addwidget.result.exists=The widget you submitted already exists.
-page.addwidget.result.success=The widget was successfully added.
-
-admin.home.title=Rave admin interface
-admin.home.shorttitle=Home
-admin.widgets.title=Rave admin interface - Widgets
-admin.widgets.shorttitle=Widgets
-admin.users.title=Rave admin interface - Users
-admin.users.shorttitle=Users
-admin.userdetail.title=Rave admin interface - User detail
-
-admin.list.noresult=No results found
-admin.list.result.x.to.y=Showing {0} - {1} of {2} results
-admin.list.search.noresult=No results found for ''{0}''
-admin.list.search.result.x.to.y=Showing {0} - {1} of {2} results that match ''{3}''
-
-widget.author=Author
-widget.authorEmail=Author's email address
-widget.description=Description
-widget.screenshotUrl=Screenshot
-widget.screenshotUrl.malformed=URL is malformed
-widget.thumbnailUrl=Thumbnail
-widget.thumbnailUrl.malformed=URL is malformed
-widget.title=Title
-widget.title.required=Title is required
-widget.titleUrl=URL the gadget title links to
-widget.titleUrl.malformed=URL is malformed
-widget.type=Type
-widget.type.OpenSocial=OpenSocial
-widget.type.W3C=W3C Widget
-widget.type.required=Choose a widget type
-widget.url=Location (URL)
-widget.url.malformed=URL is malformed
-widget.url.required=URL is required
-widget.widgetStatus.PREVIEW=This widget is waiting for approval by the site administrator.
-widget.widgetStatus.PUBLISHED=
-
+#
+# 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.
+#
+
+username.required=Username required
+username.invalid.length=Username must be at least 2 characters long
+username.invalid.pattern=Username must be at least 2 characters long and may only contain letters, numbers, \
+  _-+.@
+username.exists=Username already exists
+
+password.required=Password required
+password.invalid.length=Password must be at least 4 characters long
+
+confirmPassword.required=Confirm Password required
+confirmPassword.mismatch=Password mismatch
+
+email.required=Email required
+email.invalid=This is not a valid email address
+email.exists=This email address already exists for a user
+
+form.some.fields.required=Field marked with * are required
+form.all.fields.required=All fields are required.
+
+page.error.title=Rave has suffered a brief meltdown
+page.error.message=Please bear with us while we fetch some ice cubes.  In the meantime please try
+page.error.reload=reloading
+page.error.details=technical details
+
+page.general.back=Back to Rave
+page.general.addnewpage=Add a New Page
+page.general.confirmpassword=Confirm password:
+page.general.deletepage=Delete Page
+page.general.editpage=Edit Page
+page.general.email=Email address:
+page.general.logout=Logout
+page.general.movepage=Move Page
+page.general.movethispage=Move this page:
+page.general.movethispage.after=After {0}
+page.general.movethispage.tofirst=To First Tab (Set as Default)
+page.general.password=Password:
+page.general.screenshot=screenshot
+page.general.titlesuffix= - Rave
+page.general.thumbnail=thumbnail
+page.general.username=Username:
+
+page.general.addpage.title=Title
+page.general.addpage.layout.columns_1=One Column
+page.general.addpage.layout.columns_2=Two Columns
+page.general.addpage.layout.columns_2wn=Two Columns (wide/narrow)
+page.general.addpage.layout.columns_3=Three Columns
+page.general.addpage.layout.columns_3nwn=Three Columns (narrow/wide/narrow)
+page.general.addpage.layout.columns_4=Four Columns
+page.general.addpage.layout.columns_3nwn_1_bottom=Four Columns (narrow/wide/narrow/bottom)
+page.general.addpage.selectlayout=Select Page Layout:
+
+page.home.welcome=Hello {0}, welcome to Rave!
+
+page.login.title=Login
+page.login.createaccount=New User
+page.login.createaccount.label=Register:
+page.login.createaccount.button=Create New Account
+page.login.openid=OpenID Identity
+page.login.openid.button=Login with OpenID
+page.login.openid.fail=OpenID identification failed.
+page.login.openid.identifier=Identity:
+page.login.rememberme=Remember me
+page.login.usernamepassword=Username and Password
+page.login.usernamepassword.fail=The username or password is incorrect.
+page.login.usernamepassword.login=Login
+
+page.newaccount.title=New Account Application
+page.newaccount.button=Create Account
+
+page.store.title=Widget Store
+page.store.search=Search in widget store
+page.store.search.button=Search
+page.store.list.noresult=No widgets found
+page.store.list.result.x.to.y=Showing {0} - {1} of {2} widgets
+page.store.list.search.noresult=No widgets found for ''{0}''
+page.store.list.search.result.x.to.y=Showing {0} - {1} of {2} widgets that match ''{3}''
+
+page.userprofile.title=Update user profile
+page.userprofile.button=Update profile
+page.userprofile.openid.url=OpenID URL:
+
+page.widget.addToPage=Add to Page
+page.widget.backToStore=Back to Store
+page.widget.widgetPreview=Widget Preview
+
+page.addwidget.title=Add new widget
+page.addwidget.form.header=Widget
+page.addwidget.form.submit=Add widget
+page.addwidget.result.exists=The widget you submitted already exists.
+page.addwidget.result.success=The widget was successfully added.
+
+admin.home.title=Rave admin interface
+admin.home.shorttitle=Home
+admin.widgets.title=Rave admin interface - Widgets
+admin.widgets.shorttitle=Widgets
+admin.users.title=Rave admin interface - Users
+admin.users.shorttitle=Users
+admin.userdetail.title=Rave admin interface - User detail
+
+admin.list.noresult=No results found
+admin.list.result.x.to.y=Showing {0} - {1} of {2} results
+admin.list.search.noresult=No results found for ''{0}''
+admin.list.search.result.x.to.y=Showing {0} - {1} of {2} results that match ''{3}''
+
+widget.author=Author
+widget.authorEmail=Author's email address
+widget.description=Description
+widget.screenshotUrl=Screenshot
+widget.screenshotUrl.malformed=URL is malformed
+widget.thumbnailUrl=Thumbnail
+widget.thumbnailUrl.malformed=URL is malformed
+widget.title=Title
+widget.title.required=Title is required
+widget.titleUrl=URL the gadget title links to
+widget.titleUrl.malformed=URL is malformed
+widget.type=Type
+widget.type.OpenSocial=OpenSocial
+widget.type.W3C=W3C Widget
+widget.type.required=Choose a widget type
+widget.url=Location (URL)
+widget.url.malformed=URL is malformed
+widget.url.required=URL is required
+widget.widgetStatus.PREVIEW=This widget is waiting for approval by the site administrator.
+widget.widgetStatus.PUBLISHED=
+
+widget.general.movewidget=Move widget
+widget.general.movethiswidget=Move this widget to page:
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp Mon Oct 10 18:38:08 2011
@@ -45,6 +45,12 @@
       </h1>
     </header>
     <input id="currentPageId" type="hidden" value="${page.entityId}" />
+    <c:set var="hasOnlyOnePage">
+        <c:choose>
+            <c:when test="${fn:length(pages) == 1}">true</c:when>
+            <c:otherwise>false</c:otherwise>
+        </c:choose>
+    </c:set>
     <div id="tabsHeader">
         <%-- render the page tabs --%>
         <div id="tabs" class="rave-ui-tabs">
@@ -56,12 +62,6 @@
                          <c:otherwise>false</c:otherwise>
                      </c:choose>
                  </c:set>
-                 <c:set var="hasOnlyOnePage">
-                      <c:choose>
-                         <c:when test="${fn:length(pages) == 1}">true</c:when>
-                         <c:otherwise>false</c:otherwise>
-                     </c:choose>
-                 </c:set>
                  <div id="tab-${userPage.entityId}" class="rave-ui-tab<c:if test="${isCurrentPage}"> rave-ui-tab-selected</c:if>">
                     <div id="pageTitle-${userPage.entityId}" class="page-title" onclick="rave.viewPage(${userPage.entityId});"><c:out value="${userPage.name}"/></div>
                     <c:if test="${isCurrentPage}">
@@ -103,6 +103,14 @@
                             </div>
                             <!-- These are toolbar buttons -->
                             <div id="widget-${regionWidget.entityId}-toolbar" style="float:right;">
+                                <div id="widget-${regionWidget.entityId}-widget-menu-wrapper" class="widget-menu-wrapper">
+                                    <span id="widget-${regionWidget.entityId}-menu-button" class="widget-menu-button ui-icon ui-icon-circle-triangle-s" title="Widget Actions Menu"></span>   
+                                    <div id="widget-${regionWidget.entityId}-menu" class="widget-menu">  
+                                        <div id="widget-${regionWidget.entityId}-menu-move-item" class="widget-menu-item<c:if test='${hasOnlyOnePage}'> widget-menu-item-disabled</c:if>">
+                                            <fmt:message key="widget.general.movewidget"/>
+                                        </div>   
+                                    </div>       
+                                </div>                                                                
                                 <button id="widget-${regionWidget.entityId}-prefs"
                                         class="widget-toolbar-btn widget-toolbar-btn-prefs">
                                 </button>
@@ -165,6 +173,21 @@
             </select>
         </form>
     </div>
+    <fmt:message key="widget.general.movewidget" var="moveWidgetToPageTitle"/>
+    <div id="moveWidgetDialog" title="${moveWidgetToPageTitle}" class="dialog">
+        <div><fmt:message key="widget.general.movethiswidget"/></div>
+        <form id="moveWidgetForm">
+            <select id="moveToPageId">
+                <c:forEach var="userPage" items="${pages}">
+                    <c:if test="${userPage.entityId != page.entityId}">
+                        <option value="${userPage.entityId}">
+                            <c:out value="${userPage.name}"/>
+                        </option>
+                    </c:if>
+                </c:forEach>
+            </select>
+        </form>
+    </div>        
     <script>
         //Define the global widgets variable
         //This array will be populated by RegionWidgetRender providers.

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=1181124&r1=1181123&r2=1181124&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 Oct 10 18:38:08 2011
@@ -1,682 +1,714 @@
-/*
- * 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.
- */
-
-html {
-    background-color: #EBEBEB;
-}
-
-body {
-    color: #000000;
-    font-size: 62.5%;
-    font-family: Arial, Helvetica, sans-serif;
-    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#D7D7D3", endColorstr="#EBEBEB");
-    background: -moz-linear-gradient(center top , #D7D7D3 0%, #EBEBEB 50%) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#D7D7D3), to(#EBEBEB));
-    margin:0;
-}
-
-/* general html fields */
-
-header, nav, article, section, footer{
-    display: block;
-    margin: 0;
-    padding: 0;
-}
-
-ul, ol, table, p {
-    margin: 0;
-    padding: 0;
-}
-
-h1, h2, h3, h4, h5, h6 {
-    color: #193240;
-    text-transform: uppercase;
-}
-
-dt {
-    display: inline;
-    float: left;
-}
-
-a, a:visited, a:hover {
-    color: #107EC0;
-}
-
-a:hover {
-    background-color: #e6ebed;
-}
-
-a img {
-    border: none;
-}
-
-.clear-float {
-    clear: both;
-}
-
-.horizontal-list li, .paging li {
-    display: inline;
-    list-style: none;
-    padding:0 10px;
-}
-.horizontal-list li:last-child, .paging li:last-child {
-    padding-right: 0;
-}
-
-.paging li {
-    padding: 0;
-}
-
-.paging li:after {
-    margin: 0 10px;
-    content: "|";
-}
-
-.paging li:last-child:after {
-    margin-right: 0;
-    content: "";
-}
-
-#banner {
-    padding: 0 0 10px 10px;
-}
-
-/* Header */
-header {
-    height:50px;
-    color: #F2F2F2;
-    background-color: #222222;
-}
-
-header img {
-    max-width: 150px;
-}
-
-header a, header a:visited {
-    color: #F2F2F2;
-    text-decoration: none;
-}
-
-header a:hover {
-    color: #F2F2F2;
-    background-color: #666666;
-    text-decoration: none;
-}
-header h1 {
-    text-align: center;
-    text-transform: lowercase;
-    font-size: 1.5em;
-    margin: 0 auto;
-    width: 80%;
-    color: #F2F2F2;
-}
-
-.topnav {
-    float: right;
-    margin-right: 2%;
-}
-/* content */
-#content {
-    background-color: transparent;
-    padding: 0;
-    width: 90%;
-    margin-left:auto;
-    margin-right:auto;
-    margin-top: 10px;
-    min-height: 800px;
-}
-
-#content h1, h2, h3, h4, h5, h6 {
-    font-weight: normal;
-    margin: 10px 0 15px;
-    padding: 5px 0;
-}
-#content h1 {
-    font-size: 1.4em;
-    padding: 15px;
-}
-
-#content h2 {
-    font-size: 1.2em;
-    margin-top: 2em;
-    border-bottom: 1px solid #a3afb6;
-}
-
-#content h3, h4, h5, h6 {
-    border-bottom: none;
-    font-size: 1em;
-    margin-bottom: 0;
-}
-
-#content p {
-    margin: 1em 0;
-}
-
-/* Widgets */
-.widget {
-    padding: 5px;
-    background-color: white;
-    box-shadow: 2px 2px 4px #666666;
-    border-radius: 0 0 5px 5px;
-    height: 100%;
-}
-
-.widget-wrapper-transitional {
-    position: absolute;
-    z-index: 1000;
-    left:0.25%;
-    top: 51px;
-}
-
-.widget-wrapper-canvas {
-    position: absolute;
-    z-index: 1000;
-    left:0.25%;
-    top: 51px;
-    width: 99.5%;
-    height: 100%;
-    opacity: 1;
-    vertical-align: top;
-}
-
-.widget-a {
-    color: white;
-    width: 100px;
-    text-align: center;
-    float: right;
-    margin-right: 2%;
-}
-
-.widget-wrapper {
-    vertical-align: top;
-    margin-bottom: 20px;
-}
-
-.widget-title-bar {
-    color: #FFFFFF;
-    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#999999", endColorstr="#666666");
-    background: -moz-linear-gradient(center top , #999 0%, #666 25%) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#999), to(#666));
-    border-radius: 5px 5px 0 0;
-    padding: 2px;
-    border-bottom: solid 1px #CCCCCC;
-    box-shadow: 2px 2px 4px #666666;
-}
-
-.widget-title-bar:hover {
-    cursor: move;
-}
-
-.widget-title {
-    display: inline;
-}
-
-.widget-title a {
-    background: none;
-    color: #ffffff;
-    text-decoration: none;
-}
-
-.widget-title a:hover {
-    text-decoration: underline;
-}
-
-/*** various widget preference related classes ***/
-.widget-prefs {
-    border: 1px solid #D3D3D3;
-    background-color: white;
-    display: none;
-}
-
-.widget-prefs-required-text {
-    font-size: 0.8em;
-    margin-top: 5px;
-    margin-bottom: 5px;
-}
-
-.widget-prefs-label {
-    vertical-align: top;
-    font-size: 0.8em;
-    text-align: right;
-}
-
-.widget-prefs-label-required {
-
-}
-
-.widget-prefs-input {
-    font-family: Arial, Helvetica, sans-serif;
-    font-size: 0.8em;
-}
-
-.widget-prefs-input-required {
-
-}
-
-.widget-prefs-input-failed-validation {
-    background-color: yellow;
-}
-
-.region {
-    float: left;
-    display: block;
-    padding: 5px 5px 100px 5px; /*** bottom padding is needed for dnd when region is empty ***/
-    margin-right: 20px;
-    width:300px;
-    height: 100%;
-}
-
-.region-dragging {
-    height: 200%;
-    min-width: 250px;
-    border: 1px solid black;
-}
-
-.storeSearch, .storeBox {
-    margin: 5px auto;
-    width: 60%
-}
-.storeSearch form {
-    margin: 0;
-    float: right;
-}
-.storeSearch form p {
-    margin: 0;
-}
-
-#storeWidgetDetail {
-    width: 100%;
-}
-
-.storeItem {
-    border: 1px solid #B3C4CF;
-    margin: 5px auto 5px auto;
-    padding: 10px;
-    background-color: #F2F2F2;
-    color: black;
-    border-radius: 5px;
-    box-shadow: 2px 2px 2px black;
-    width: 60%;
-}
-
-#widget-content {
-    color: #222222;
-    background-color: #F2F2F2;
-    box-shadow: 5px 5px 5px black;
-    border-radius: 5px;
-    margin-left: auto;
-    margin-right: auto;
-    padding: 10px;
-    width: 1024px;
-}
-
-.widgetDetailLeft {
-   padding-left: 10px;
-   padding-right: 10px;
-   vertical-align: top;
-   width: 150px;
-   float: left;
-}
-
-.widgetDetailCenter {
-    padding-left: 10px;
-    padding-right: 10px;
-    vertical-align: top;
-    float: left;
-    width: 50%;
-}
-
-.widgetDetailRight {
-  padding: 0 10px;
-  width: 300px;
-  vertical-align: top;
-  float: left;
-}
-
-.widgetScreenshot img {
-  max-width: 280px;
-}
-ul.storeItems {
-    padding: 0;
-}
-
-ul.storeItems li{
-    list-style: none;
-}
-
-.storeItemLeft {
-   padding-left: 10px;
-   padding-right: 10px;
-   vertical-align: top;
-   width: 150px;
-   float: left;
-
-}
-
-.storeItemCenter {
-    padding-left: 10px;
-    padding-right: 10px;
-    vertical-align: top;
-    float: left;
-    width: 50%;
-}
-
-.storeButton {
-    float: right;
-}
-
-.ui-sortable-placeholder {
-    border: 1px dotted black;
-    visibility: visible !important;
-    background-color: #DDD;
-}
-
-.ui-sortable-placeholder * {
-    visibility: hidden;
-}
-
-button.widget-toolbar-btn {
-    width: 1em;
-}
-
-button.widget-toolbar-btn-prefs {
-    display: none;
-}
-
-.widget-toolbar-toggle-collapse {
-    display: inline-block;
-    vertical-align: middle;
-    cursor: pointer;
-}
-
-/* Form fields */
-
-fieldset{
-    margin: 0;
-    border:none
-}
-p label {
-    width: 120px;
-    float: left;
-    display: block;
-    position: relative;
-}
-
-label.formradio {
-    float: none;
-    left: 0;
-    margin-left: 120px;
-    margin-bottom: 0.4em;
-    margin-right: 0;
-    position: static;
-    top: auto;
-    width: auto;
-}
-
-input.long, textarea.long {
-    width:400px;
-}
-
-
-/* Associated with JQuery validation CSS */
-.error {
-    color: #ff0000;
-}
-
-span.error, label.error {
-    font-size: 10px;
-    display: block;
-    float: none;
-    margin: 0.5em 0 auto 120px;
-}
-
-.warn {
-  font-weight: bold;
-}
-
-/* End of form fields */
-
-#tabsHeader {
-    background-color: #FFFFFF;
-}
-
-#tabs {
-    border-bottom: 1px solid #B4C4CF;
-    margin: 0;
-    padding: 10px 15px 0 13px;
-    white-space: nowrap;
-}
-
-.rave-ui-tab {
-    background-color: #FFFFFF;
-    border: 1px solid #B4C4CF;
-    color: #767676;
-    display: inline-block;
-    font-style: italic;
-    font-weight: normal;
-    height: 25px;
-    position: relative;
-    top: 1px;
-}
-
-.rave-ui-tab a, .rave-ui-tab a:visited {
-    color: #767676;
-    text-decoration: none;
-}
-
-.rave-ui-tab:hover, .rave-ui-tab a:hover {
-    background-color: #D7D7D3;
-    color: #000000;
-}
-
-.rave-ui-tab-selected, .rave-ui-tab-selected:hover {
-    background-color: #D7D7D3;
-    border-bottom: 1px solid #D7D7D3;
-    color: #000000;
-    font-style: normal;
-    font-weight: bold;
-}
-
-#dialog {
-    width:400px;
-    display: none;
-}
-#dialog label { display:block; }
-#dialog input { display:block; }
-#dialog label { margin-top: 0.5em; }
-#dialog input { width: 95%; }
-#dialog textarea { width: 95%; }
-#add_page {
-    cursor: pointer;
-    width: 18px;
-    display: inline-block;
-    vertical-align: middle;
-    margin-left: 10px;
-    padding-bottom: 4px;
-    padding-top: 3px;
-}
-
-#pageContent, .pageContent {
-    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#D7D7D3", endColorstr="#EBEBEB");
-    background: -moz-linear-gradient(center top , #D7D7D3 0%, #EBEBEB 50%) repeat scroll 0 0 transparent;
-    background: -webkit-gradient(linear, left top, left bottom, from(#D7D7D3), to(#EBEBEB));
-}
-
-.page-title {
-    display: inline-block;
-    padding: 5px 10px;
-    cursor: pointer;
-}
-
-/* page menu related styles */
-#pageMenuWrapper {
-    position: relative;
-    display: inline-block;
-    vertical-align: middle;
-}
-.page-menu {
-    border: 1px solid black;
-    position: absolute;
-    display: none;
-    left: 18px;
-    top: 0;
-    width: 80px;
-    background-color: #FFFFFF;
-    z-index: 1000;
-    cursor: pointer;
-}
-.page-menu-item {
-    padding: 3px;
-}
-.page-menu-item:hover {
-    background-color: #B4C4CF;
-}
-.page-menu-item-disabled {
-    color: #D3D3D3;
-}
-#pageMenuButton {
-    cursor: pointer;
-    margin-right: 10px;
-}
-#errorStack {
-    display: none;
-}
-
-.errorMessage {
-    text-align: center;
-    font-size: 150%;
-}
-.errorLogo {
-    text-align: center;
-}
-
-/** Admin interface **/
-.admincontent {
-    margin: 0 auto;
-    width: 80%;
-    padding:0 20px;
-    font-size:1.1em;
-}
-
-.admincontent .searchbox {
-    float:right;
-    margin-top:1em;
-}
-
-.searchbox form, .searchbox fieldset {
-    display:inline;
-    height:1em;
-    margin:0;
-    padding:0;
-}
-
-.admincontent h2 {
-    margin-top: 0;
-    padding-top:1em;
-}
-
-.admincontent table {
-    margin: 1.5em 0;
-    padding: 0;
-    border-collapse: collapse;
-    font-size: 13px;
-    border: 1px solid #ddd;
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-    border-radius: 4px;
-}
-
-.admincontent table th,.admincontent table td {
-    padding: 5px 5px 4px;
-    line-height: 1.5em;
-    text-align: left;
-}
-
-.admincontent table th {
-    padding-top: 4px;
-    font-weight: bold;
-    vertical-align: middle;
-    border-bottom: 1px solid #ddd;
-    background-color: #000000;
-    color: #ffffff;
-}
-
-.admincontent table td {
-    vertical-align: top;
-}
-
-.admincontent table th+th, .admincontent table td+td {
-    border-left: 1px solid #ddd;
-}
-
-.admincontent table tr+tr td {
-    border-top: 1px solid #ddd;
-}
-
-.admincontent table tbody tr:first-child td:first-child {
-    -webkit-border-radius: 4px 0 0 0;
-    -moz-border-radius: 4px 0 0 0;
-    border-radius: 4px 0 0 0;
-}
-
-.admincontent table tbody tr:first-child td:last-child {
-    -webkit-border-radius: 0 4px 0 0;
-    -moz-border-radius: 0 4px 0 0;
-    border-radius: 0 4px 0 0;
-}
-
-.admincontent table tbody tr:last-child td:first-child {
-    -webkit-border-radius: 0 0 0 4px;
-    -moz-border-radius: 0 0 0 4px;
-    border-radius: 0 0 0 4px;
-}
-
-.admincontent table tbody tr:last-child td:last-child {
-    -webkit-border-radius: 0 0 4px 0;
-    -moz-border-radius: 0 0 4px 0;
-    border-radius: 0 0 4px 0;
-}
-
-.admincontent tbody tr:nth-child(odd) {
-    background-color: #D3D3D3;
-}
-
-.admincontent tbody tr:hover {
-    background-color: #B4C4CF;
-}
-
-.admincontent table a, .admincontent table a:visited {
-    color: #000000;
-    text-decoration:none;
-}
-
-.admincontent tbody tr:hover a, .admincontent table a:hover {
-    background-color: transparent;
-    text-decoration: underline;
-}
-
-.booleancell {
-    width: 50px;
-}
-.textcell {
-    width: 150px;
-}
-.largetextcell {
-    width: 300px
-}
+/*
+ * 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.
+ */
+
+html {
+    background-color: #EBEBEB;
+}
+
+body {
+    color: #000000;
+    font-size: 62.5%;
+    font-family: Arial, Helvetica, sans-serif;
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#D7D7D3", endColorstr="#EBEBEB");
+    background: -moz-linear-gradient(center top , #D7D7D3 0%, #EBEBEB 50%) repeat scroll 0 0 transparent;
+    background: -webkit-gradient(linear, left top, left bottom, from(#D7D7D3), to(#EBEBEB));
+    margin:0;
+}
+
+/* general html fields */
+
+header, nav, article, section, footer{
+    display: block;
+    margin: 0;
+    padding: 0;
+}
+
+ul, ol, table, p {
+    margin: 0;
+    padding: 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    color: #193240;
+    text-transform: uppercase;
+}
+
+dt {
+    display: inline;
+    float: left;
+}
+
+a, a:visited, a:hover {
+    color: #107EC0;
+}
+
+a:hover {
+    background-color: #e6ebed;
+}
+
+a img {
+    border: none;
+}
+
+.clear-float {
+    clear: both;
+}
+
+.horizontal-list li, .paging li {
+    display: inline;
+    list-style: none;
+    padding:0 10px;
+}
+.horizontal-list li:last-child, .paging li:last-child {
+    padding-right: 0;
+}
+
+.paging li {
+    padding: 0;
+}
+
+.paging li:after {
+    margin: 0 10px;
+    content: "|";
+}
+
+.paging li:last-child:after {
+    margin-right: 0;
+    content: "";
+}
+
+#banner {
+    padding: 0 0 10px 10px;
+}
+
+/* Header */
+header {
+    height:50px;
+    color: #F2F2F2;
+    background-color: #222222;
+}
+
+header img {
+    max-width: 150px;
+}
+
+header a, header a:visited {
+    color: #F2F2F2;
+    text-decoration: none;
+}
+
+header a:hover {
+    color: #F2F2F2;
+    background-color: #666666;
+    text-decoration: none;
+}
+header h1 {
+    text-align: center;
+    text-transform: lowercase;
+    font-size: 1.5em;
+    margin: 0 auto;
+    width: 80%;
+    color: #F2F2F2;
+}
+
+.topnav {
+    float: right;
+    margin-right: 2%;
+}
+/* content */
+#content {
+    background-color: transparent;
+    padding: 0;
+    width: 90%;
+    margin-left:auto;
+    margin-right:auto;
+    margin-top: 10px;
+    min-height: 800px;
+}
+
+#content h1, h2, h3, h4, h5, h6 {
+    font-weight: normal;
+    margin: 10px 0 15px;
+    padding: 5px 0;
+}
+#content h1 {
+    font-size: 1.4em;
+    padding: 15px;
+}
+
+#content h2 {
+    font-size: 1.2em;
+    margin-top: 2em;
+    border-bottom: 1px solid #a3afb6;
+}
+
+#content h3, h4, h5, h6 {
+    border-bottom: none;
+    font-size: 1em;
+    margin-bottom: 0;
+}
+
+#content p {
+    margin: 1em 0;
+}
+
+/* Widgets */
+.widget {
+    padding: 5px;
+    background-color: white;
+    box-shadow: 2px 2px 4px #666666;
+    border-radius: 0 0 5px 5px;
+    height: 100%;
+}
+
+.widget-wrapper-transitional {
+    position: absolute;
+    z-index: 1000;
+    left:0.25%;
+    top: 51px;
+}
+
+.widget-wrapper-canvas {
+    position: absolute;
+    z-index: 1000;
+    left:0.25%;
+    top: 51px;
+    width: 99.5%;
+    height: 100%;
+    opacity: 1;
+    vertical-align: top;
+}
+
+.widget-a {
+    color: white;
+    width: 100px;
+    text-align: center;
+    float: right;
+    margin-right: 2%;
+}
+
+.widget-wrapper {
+    vertical-align: top;
+    margin-bottom: 20px;
+}
+
+.widget-title-bar {
+    color: #FFFFFF;
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#999999", endColorstr="#666666");
+    background: -moz-linear-gradient(center top , #999 0%, #666 25%) repeat scroll 0 0 transparent;
+    background: -webkit-gradient(linear, left top, left bottom, from(#999), to(#666));
+    border-radius: 5px 5px 0 0;
+    padding: 2px;
+    border-bottom: solid 1px #CCCCCC;
+    box-shadow: 2px 2px 4px #666666;
+}
+
+.widget-title-bar:hover {
+    cursor: move;
+}
+
+.widget-title {
+    display: inline;
+}
+
+.widget-title a {
+    background: none;
+    color: #ffffff;
+    text-decoration: none;
+}
+
+.widget-title a:hover {
+    text-decoration: underline;
+}
+
+/*** various widget preference related classes ***/
+.widget-prefs {
+    border: 1px solid #D3D3D3;
+    background-color: white;
+    display: none;
+}
+
+.widget-prefs-required-text {
+    font-size: 0.8em;
+    margin-top: 5px;
+    margin-bottom: 5px;
+}
+
+.widget-prefs-label {
+    vertical-align: top;
+    font-size: 0.8em;
+    text-align: right;
+}
+
+.widget-prefs-label-required {
+
+}
+
+.widget-prefs-input {
+    font-family: Arial, Helvetica, sans-serif;
+    font-size: 0.8em;
+}
+
+.widget-prefs-input-required {
+
+}
+
+.widget-prefs-input-failed-validation {
+    background-color: yellow;
+}
+
+.region {
+    float: left;
+    display: block;
+    padding: 5px 5px 100px 5px; /*** bottom padding is needed for dnd when region is empty ***/
+    margin-right: 20px;
+    width:300px;
+    height: 100%;
+}
+
+.region-dragging {
+    height: 200%;
+    min-width: 250px;
+    border: 1px solid black;
+}
+
+.storeSearch, .storeBox {
+    margin: 5px auto;
+    width: 60%
+}
+.storeSearch form {
+    margin: 0;
+    float: right;
+}
+.storeSearch form p {
+    margin: 0;
+}
+
+#storeWidgetDetail {
+    width: 100%;
+}
+
+.storeItem {
+    border: 1px solid #B3C4CF;
+    margin: 5px auto 5px auto;
+    padding: 10px;
+    background-color: #F2F2F2;
+    color: black;
+    border-radius: 5px;
+    box-shadow: 2px 2px 2px black;
+    width: 60%;
+}
+
+#widget-content {
+    color: #222222;
+    background-color: #F2F2F2;
+    box-shadow: 5px 5px 5px black;
+    border-radius: 5px;
+    margin-left: auto;
+    margin-right: auto;
+    padding: 10px;
+    width: 1024px;
+}
+
+.widgetDetailLeft {
+   padding-left: 10px;
+   padding-right: 10px;
+   vertical-align: top;
+   width: 150px;
+   float: left;
+}
+
+.widgetDetailCenter {
+    padding-left: 10px;
+    padding-right: 10px;
+    vertical-align: top;
+    float: left;
+    width: 50%;
+}
+
+.widgetDetailRight {
+  padding: 0 10px;
+  width: 300px;
+  vertical-align: top;
+  float: left;
+}
+
+.widgetScreenshot img {
+  max-width: 280px;
+}
+ul.storeItems {
+    padding: 0;
+}
+
+ul.storeItems li{
+    list-style: none;
+}
+
+.storeItemLeft {
+   padding-left: 10px;
+   padding-right: 10px;
+   vertical-align: top;
+   width: 150px;
+   float: left;
+
+}
+
+.storeItemCenter {
+    padding-left: 10px;
+    padding-right: 10px;
+    vertical-align: top;
+    float: left;
+    width: 50%;
+}
+
+.storeButton {
+    float: right;
+}
+
+.ui-sortable-placeholder {
+    border: 1px dotted black;
+    visibility: visible !important;
+    background-color: #DDD;
+}
+
+.ui-sortable-placeholder * {
+    visibility: hidden;
+}
+
+button.widget-toolbar-btn {
+    width: 1em;
+}
+
+button.widget-toolbar-btn-prefs {
+    display: none;
+}
+
+.widget-toolbar-toggle-collapse {
+    display: inline-block;
+    vertical-align: middle;
+    cursor: pointer;
+}
+
+/* Form fields */
+
+fieldset{
+    margin: 0;
+    border:none
+}
+p label {
+    width: 120px;
+    float: left;
+    display: block;
+    position: relative;
+}
+
+label.formradio {
+    float: none;
+    left: 0;
+    margin-left: 120px;
+    margin-bottom: 0.4em;
+    margin-right: 0;
+    position: static;
+    top: auto;
+    width: auto;
+}
+
+input.long, textarea.long {
+    width:400px;
+}
+
+
+/* Associated with JQuery validation CSS */
+.error {
+    color: #ff0000;
+}
+
+span.error, label.error {
+    font-size: 10px;
+    display: block;
+    float: none;
+    margin: 0.5em 0 auto 120px;
+}
+
+.warn {
+  font-weight: bold;
+}
+
+/* End of form fields */
+
+#tabsHeader {
+    background-color: #FFFFFF;
+}
+
+#tabs {
+    border-bottom: 1px solid #B4C4CF;
+    margin: 0;
+    padding: 10px 15px 0 13px;
+    white-space: nowrap;
+}
+
+.rave-ui-tab {
+    background-color: #FFFFFF;
+    border: 1px solid #B4C4CF;
+    color: #767676;
+    display: inline-block;
+    font-style: italic;
+    font-weight: normal;
+    height: 25px;
+    position: relative;
+    top: 1px;
+}
+
+.rave-ui-tab a, .rave-ui-tab a:visited {
+    color: #767676;
+    text-decoration: none;
+}
+
+.rave-ui-tab:hover, .rave-ui-tab a:hover {
+    background-color: #D7D7D3;
+    color: #000000;
+}
+
+.rave-ui-tab-selected, .rave-ui-tab-selected:hover {
+    background-color: #D7D7D3;
+    border-bottom: 1px solid #D7D7D3;
+    color: #000000;
+    font-style: normal;
+    font-weight: bold;
+}
+
+#dialog {
+    width:400px;
+    display: none;
+}
+#dialog label { display:block; }
+#dialog input { display:block; }
+#dialog label { margin-top: 0.5em; }
+#dialog input { width: 95%; }
+#dialog textarea { width: 95%; }
+#add_page {
+    cursor: pointer;
+    width: 18px;
+    display: inline-block;
+    vertical-align: middle;
+    margin-left: 10px;
+    padding-bottom: 4px;
+    padding-top: 3px;
+}
+
+#pageContent, .pageContent {
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#D7D7D3", endColorstr="#EBEBEB");
+    background: -moz-linear-gradient(center top , #D7D7D3 0%, #EBEBEB 50%) repeat scroll 0 0 transparent;
+    background: -webkit-gradient(linear, left top, left bottom, from(#D7D7D3), to(#EBEBEB));
+}
+
+.page-title {
+    display: inline-block;
+    padding: 5px 10px;
+    cursor: pointer;
+}
+
+/* page menu related styles */
+#pageMenuWrapper {
+    position: relative;
+    display: inline-block;
+    vertical-align: middle;
+}
+.page-menu {
+    border: 1px solid black;
+    position: absolute;
+    display: none;
+    left: 18px;
+    top: 0;
+    width: 80px;
+    background-color: #FFFFFF;
+    z-index: 1000;
+    cursor: pointer;
+}
+.page-menu-item {
+    padding: 3px;
+}
+.page-menu-item:hover {
+    background-color: #B4C4CF;
+}
+.page-menu-item-disabled {
+    color: #D3D3D3;
+}
+#pageMenuButton {
+    cursor: pointer;
+    margin-right: 10px;
+}
+
+/* widget menu related styles */
+.widget-menu-wrapper {
+    position: relative;
+    display: inline-block;
+    vertical-align: middle;
+}
+.widget-menu {
+    border: 1px solid black;
+    position: absolute;
+    display: none;
+    left: 18px;
+    top: 0;
+    width: 80px;
+    background-color: #FFFFFF;
+    z-index: 1000;
+    cursor: pointer;
+}
+.widget-menu-item {
+    padding: 3px;
+    color: #000000;
+}
+.widget-menu-item:hover {
+    background-color: #B4C4CF;
+}
+.widget-menu-item-disabled {
+    color: #D3D3D3;
+}
+.widget-menu-button {
+    cursor: pointer;
+}
+
+#errorStack {
+    display: none;
+}
+
+.errorMessage {
+    text-align: center;
+    font-size: 150%;
+}
+.errorLogo {
+    text-align: center;
+}
+
+/** Admin interface **/
+.admincontent {
+    margin: 0 auto;
+    width: 80%;
+    padding:0 20px;
+    font-size:1.1em;
+}
+
+.admincontent .searchbox {
+    float:right;
+    margin-top:1em;
+}
+
+.searchbox form, .searchbox fieldset {
+    display:inline;
+    height:1em;
+    margin:0;
+    padding:0;
+}
+
+.admincontent h2 {
+    margin-top: 0;
+    padding-top:1em;
+}
+
+.admincontent table {
+    margin: 1.5em 0;
+    padding: 0;
+    border-collapse: collapse;
+    font-size: 13px;
+    border: 1px solid #ddd;
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    border-radius: 4px;
+}
+
+.admincontent table th,.admincontent table td {
+    padding: 5px 5px 4px;
+    line-height: 1.5em;
+    text-align: left;
+}
+
+.admincontent table th {
+    padding-top: 4px;
+    font-weight: bold;
+    vertical-align: middle;
+    border-bottom: 1px solid #ddd;
+    background-color: #000000;
+    color: #ffffff;
+}
+
+.admincontent table td {
+    vertical-align: top;
+}
+
+.admincontent table th+th, .admincontent table td+td {
+    border-left: 1px solid #ddd;
+}
+
+.admincontent table tr+tr td {
+    border-top: 1px solid #ddd;
+}
+
+.admincontent table tbody tr:first-child td:first-child {
+    -webkit-border-radius: 4px 0 0 0;
+    -moz-border-radius: 4px 0 0 0;
+    border-radius: 4px 0 0 0;
+}
+
+.admincontent table tbody tr:first-child td:last-child {
+    -webkit-border-radius: 0 4px 0 0;
+    -moz-border-radius: 0 4px 0 0;
+    border-radius: 0 4px 0 0;
+}
+
+.admincontent table tbody tr:last-child td:first-child {
+    -webkit-border-radius: 0 0 0 4px;
+    -moz-border-radius: 0 0 0 4px;
+    border-radius: 0 0 0 4px;
+}
+
+.admincontent table tbody tr:last-child td:last-child {
+    -webkit-border-radius: 0 0 4px 0;
+    -moz-border-radius: 0 0 4px 0;
+    border-radius: 0 0 4px 0;
+}
+
+.admincontent tbody tr:nth-child(odd) {
+    background-color: #D3D3D3;
+}
+
+.admincontent tbody tr:hover {
+    background-color: #B4C4CF;
+}
+
+.admincontent table a, .admincontent table a:visited {
+    color: #000000;
+    text-decoration:none;
+}
+
+.admincontent tbody tr:hover a, .admincontent table a:hover {
+    background-color: transparent;
+    text-decoration: underline;
+}
+
+.booleancell {
+    width: 50px;
+}
+.textcell {
+    width: 150px;
+}
+.largetextcell {
+    width: 300px
+}
\ No newline at end of file

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_api.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_api.js?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_api.js (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_api.js Mon Oct 10 18:38:08 2011
@@ -213,7 +213,27 @@ rave.api = rave.api || (function() {
                         }
                     }
                 }).error(handleError);
-        }        
+        }
+
+        function moveWidgetToPage(args) {
+            var data = {};
+            if (args.toPageId) {
+                data["toPageId"] = args.toPageId;
+                data["regionWidgetId"] = args.regionWidgetId;
+            }
+
+            $.post(rave.getContext() + path + "page/" + args.toPageId + "/moveWidget",
+                data,
+                function(result) {
+                    if (result.error) {
+                        handleRpcError(result);
+                    } else {
+                        if (typeof args.successCallback == 'function') {
+                            args.successCallback(result);
+                        }
+                    }
+                }).error(handleError);
+        }
 
         function updatePagePrefs(args) {
             $.post(rave.getContext() + path + "page/" + args.pageId + "/update",
@@ -264,7 +284,8 @@ rave.api = rave.api || (function() {
             addPage: addPage,
             updatePagePrefs: updatePagePrefs,
             getPagePrefs: getPagePrefs,
-            movePage: movePage
+            movePage: movePage,
+            moveWidgetToPage: moveWidgetToPage
         };
 
     })();

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_layout.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_layout.js?rev=1181124&r1=1181123&r2=1181124&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_layout.js (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave_layout.js Mon Oct 10 18:38:08 2011
@@ -149,7 +149,7 @@ rave.layout = rave.layout || (function()
             if (!$menuItemDelete.hasClass("page-menu-item-disabled")) {
                 $menuItemMove.bind('click', function(event) {
                     pageMenu.hide();                 
-                    $movePageDialog.dialog("open");                                             
+                    $movePageDialog.dialog("open");
                     // prevent the menu button click event from bubbling up to parent 
                     // DOM object event handlers such as the page tab click event
                     event.stopPropagation();
@@ -167,6 +167,105 @@ rave.layout = rave.layout || (function()
         }
     })();
 
+
+    // the modal dialog for moving a widget
+    var $moveWidgetDialog = $("#moveWidgetDialog").dialog({
+            autoOpen: false,
+            modal: true,
+            buttons: {
+                    Move: function() {
+                            moveWidgetToPage($(this).data('regionWidgetId'));
+                    },
+                    Cancel: function() {
+                            $( this ).dialog( "close" );
+                    }
+            },
+            open: function() {
+                    $("#moveToPageId").focus();
+            },
+            close: function() {
+                    $("#moveWidgetForm")[0].reset();
+            }
+    });
+
+
+    // widget menu related functions
+    var widgetMenu = (function() {
+        var $menu ;
+        var $menuItemMove ;
+
+        function hideMenu() {
+            $(".widget-menu-button").each(function(index, element) {
+                if (!$(element).hasClass("widget-menu-item-disabled")) {
+                    $menu = $("#widget-" + rave.getObjectIdFromDomId(this.id) + "-menu");
+                    $menu.hide();
+                }
+            });
+        }
+
+        function showMenu() {
+            $menu.show();
+        }
+
+        /**
+         * Initializes the private widgetMenu closure
+         * - binds click event handler to menu button
+         * - binds menu item click event handlers
+         * - binds body click event handler to close the menu
+         */
+        function init() {
+            // initialize the widget menu and button
+            $(".widget-menu-button").each(function(index, element) {
+                if (!$(element).hasClass("widget-menu-item-disabled")) {
+                    $(element).bind('click', function(event) {
+                        $menu = $("#widget-" + rave.getObjectIdFromDomId(this.id) + "-menu");                        
+                        $menu.toggle();
+                        // prevent the menu button click event from bubbling up to parent
+                        // DOM object event handlers such as the page tab click event
+                        event.stopPropagation();
+                    });
+                }
+            });
+
+            $(".widget-menu-item").each(function(index, element) {
+                if (!$(element).hasClass("widget-menu-item-disabled")) {
+                    $(element).bind('click', function(event) {
+                        $menu = $("#widget-" + rave.getObjectIdFromDomId(this.id) + "-menu");
+                        $menuItemMove = $("#widget-" + rave.getObjectIdFromDomId(this.id) + "-menu-move-item") ;
+                        $moveWidgetDialog
+                            .data('regionWidgetId', rave.getObjectIdFromDomId(this.id))
+                            .dialog("open");
+                        // prevent the menu button click event from bubbling up to parent
+                        // DOM object event handlers such as the page tab click event
+                        event.stopPropagation();
+                    });
+                }
+            });
+
+            // close the widget menu if the user clicks outside of it
+            $("html").click(widgetMenu.hide);
+        }
+
+        return {
+            init: init,
+            hide: hideMenu,
+            show: showMenu
+        }
+    })();
+
+    /**
+     * Submits the RPC call to move the widget to a new page
+     */
+    function moveWidgetToPage(regionWidgetId) {
+        var toPageId = $("#moveToPageId").val();
+        var args = { toPageId: toPageId,
+                     regionWidgetId: regionWidgetId,
+                     successCallback: function() { rave.viewPage(toPageId); }
+                   };
+        // send the rpc request to move the widget to new page
+        rave.api.rpc.moveWidgetToPage(args);
+    }
+
     /**
      * Submits the RPC call to add a new page if form validation passes
      */        
@@ -190,7 +289,7 @@ rave.layout = rave.layout || (function()
      * Submits the RPC call to move the page to a new render sequence
      */        
     function movePage() {
-        var moveAfterPageId = $("#moveAfterPageId").val();        
+        var moveAfterPageId = $("#moveAfterPageId").val();
         var args = { pageId: $("#currentPageId").val(),
                      successCallback: function(result) { rave.viewPage(result.result.entityId); }
                    };
@@ -238,6 +337,7 @@ rave.layout = rave.layout || (function()
                 .show();
 
         pageMenu.init();
+        widgetMenu.init();
     }
    
     // public rave.layout API