From cac41478d2a9f039ecc45b15ed7d371256670503 Mon Sep 17 00:00:00 2001 From: Kevin Roast Date: Tue, 12 Sep 2006 17:23:38 +0000 Subject: [PATCH] . Checkpoint of WCM UI - Create Website Wizard now creates the appropriate structure of stores and layers for a website - A website has a sandbox comprising of a staging area and a preview area layered ontop of that - Each user has a sandbox comprising of a main area (layered ontop of the staging area) and a preview area layered ontop of that - Added store level meta-data to tag the website stores with appropriate DNS names and markers for sandbox-id and sandbox types . AVM "reallybad.jsp" demo page renamed to avm.jsp with a few UI tweaks for easier command input etc. - removed the terrible.html as no longer required - just launch avm.jsp directly git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3772 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 5 + .../alfresco/web-client-config-navigation.xml | 8 + .../alfresco/web/bean/wcm/AVMConstants.java | 14 +- .../web/bean/wcm/CreateWebsiteWizard.java | 166 +++++++++++++++--- source/web/images/icons/sandbox.gif | Bin 0 -> 1039 bytes source/web/images/icons/sandbox_large.gif | Bin 0 -> 1688 bytes .../images/icons/space-icon-website-16.gif | Bin 0 -> 1039 bytes .../web/images/icons/space-icon-website.gif | Bin 0 -> 1688 bytes source/web/jsp/wcm/browse-website.jsp | 147 ++++++++++++++++ 9 files changed, 318 insertions(+), 22 deletions(-) create mode 100644 source/web/images/icons/sandbox.gif create mode 100644 source/web/images/icons/sandbox_large.gif create mode 100644 source/web/images/icons/space-icon-website-16.gif create mode 100644 source/web/images/icons/space-icon-website.gif create mode 100644 source/web/jsp/wcm/browse-website.jsp diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 679edbafb0..7d6c8e76b4 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -791,6 +791,11 @@ create_website_step1_title=Step One - Website Details create_website_step1_desc=Enter the information about the website. create_website_finish_instruction=To close this wizard and create your website space click Finish. To review or change your selections click Back. +# Browse Website and Sandboxes messages +title_browse_website=Browse Website Sandboxes +website_info=Use this view to browse the staging area and user sandboxes for a website. +staging_sandbox=Staging Sandbox + # New User Wizard messages new_user_title=New User Wizard new_user_title_edit=Edit User Wizard diff --git a/config/alfresco/web-client-config-navigation.xml b/config/alfresco/web-client-config-navigation.xml index 0dab5a7ec2..f25b0fc8c5 100644 --- a/config/alfresco/web-client-config-navigation.xml +++ b/config/alfresco/web-client-config-navigation.xml @@ -42,4 +42,12 @@ + + + + + + + + diff --git a/source/java/org/alfresco/web/bean/wcm/AVMConstants.java b/source/java/org/alfresco/web/bean/wcm/AVMConstants.java index 60239d629d..2ddea36465 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMConstants.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMConstants.java @@ -19,7 +19,7 @@ package org.alfresco.web.bean.wcm; /** * @author Kevin Roast */ -public class AVMConstants +public final class AVMConstants { /** * Private constructor @@ -28,10 +28,22 @@ public class AVMConstants { } + // names of the stores representing the layers for an AVM website public final static String STORE_STAGING = "-staging"; public final static String STORE_MAIN = "-main"; public final static String STORE_PREVIEW = "-preview"; + // system directories at the top level of an AVM website public final static String DIR_APPBASE = "appBase"; public final static String DIR_WEBAPPS = "avm_webapps"; + + // system property keys for sandbox identification and DNS virtualisation mapping + public final static String PROP_SANDBOXID = ".sandbox-id."; + public final static String PROP_SANDBOX_STAGING_MAIN = ".sandbox.staging.main"; + public final static String PROP_SANDBOX_STAGING_PREVIEW = ".sandbox.staging.preview"; + public final static String PROP_SANDBOX_AUTHOR_MAIN = ".sandbox.author.main"; + public final static String PROP_SANDBOX_AUTHOR_PREVIEW = ".sandbox.author.preview"; + public final static String PROP_DNS = ".dns."; + + public final static String SPACE_ICON_WEBSITE = "space-icon-website"; } diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java index af0f1b7df2..a7ae2a90fe 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java @@ -26,15 +26,16 @@ import javax.faces.context.FacesContext; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; +import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.service.cmr.avm.AVMStoreDescriptor; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.alfresco.util.GUID; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Repository; -import org.alfresco.web.bean.spaces.CreateSpaceWizard; import org.alfresco.web.bean.wizard.BaseWizardBean; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -89,22 +90,22 @@ public class CreateWebsiteWizard extends BaseWizardBean // apply the uifacets aspect - icon, title and description props Map uiFacetsProps = new HashMap(4); - uiFacetsProps.put(ContentModel.PROP_ICON, CreateSpaceWizard.DEFAULT_SPACE_ICON_NAME); + uiFacetsProps.put(ContentModel.PROP_ICON, AVMConstants.SPACE_ICON_WEBSITE); uiFacetsProps.put(ContentModel.PROP_TITLE, this.title); uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, this.description); this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_UIFACETS, uiFacetsProps); - // TODO: create layers for invited users // TODO: invite users with appropriate permissions into this folder - // create the AVM store to represent the newly created location website - this.avmService.createAVMStore(this.name); - AVMStoreDescriptor avmStore = this.avmService.getAVMStore(this.name); - this.avmService.createDirectory("/", "appBase"); - this.avmService.createDirectory("/appBase", "avm_webapps"); - this.avmService.createDirectory("/appBase/avm_webapps", this.name); + // create the AVM stores (layers) to represent the newly created location website + createStagingSandbox(this.name); + // create layer for current user (TODO: based on role) + createUserSandbox(this.name, Application.getCurrentUser(context).getUserName()); + // TODO: create layers for invited users based on roles + + // TODO: import the ZIP structure into the AVM staging store // set the property on the node to reference the AVM store this.nodeService.setProperty(nodeRef, ContentModel.PROP_AVMSTORE, this.name); @@ -216,26 +217,149 @@ public class CreateWebsiteWizard extends BaseWizardBean return this.websitesFolderId; } - private void createStagingStore(String name) + /** + * Create the staging sandbox for the named store. + * + * A staging sandbox is comprised of two stores, the first named 'storename-staging' with a + * preview store named 'storename-preview' layered over the staging store. + * + * Various store meta-data properties are set including: + * Identifier for store-types: .sandbox.staging.main and .sandbox.staging.preview + * Store-id: .sandbox-id. (unique across all stores in the sandbox) + * DNS: .dns. = + * + * @param name The store name to create the sandbox for + */ + private void createStagingSandbox(String name) { + // create the 'staging' store for the website String stagingStore = name + AVMConstants.STORE_STAGING; this.avmService.createAVMStore(stagingStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + stagingStore); + + // create the system directories 'appBase' and 'avm_webapps' String path = stagingStore + ":/"; this.avmService.createDirectory(path, AVMConstants.DIR_APPBASE); - path += '/' + AVMConstants.DIR_APPBASE; + path += AVMConstants.DIR_APPBASE; this.avmService.createDirectory(path, AVMConstants.DIR_WEBAPPS); - } - - private void createSandboxStores(String name, String username) - { - String sandboxStore = name + '-' + username + AVMConstants.STORE_MAIN; - this.avmService.createAVMStore(sandboxStore); - String path = sandboxStore + ":/"; - this.avmService.createLayeredDirectory(name + AVMConstants.STORE_STAGING, path, AVMConstants.DIR_APPBASE); + // tag the store with the store type + this.avmService.setStoreProperty(stagingStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_STAGING_MAIN), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(stagingStore); + + + // create the 'preview' store for the website String previewStore = name + AVMConstants.STORE_PREVIEW; this.avmService.createAVMStore(previewStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + previewStore); + + // create a layered directory pointing to 'appBase' in the staging area path = previewStore + ":/"; - this.avmService.createLayeredDirectory(name + AVMConstants.STORE_STAGING, path, AVMConstants.DIR_APPBASE); + String targetPath = name + AVMConstants.STORE_STAGING + ":/" + AVMConstants.DIR_APPBASE; + this.avmService.createLayeredDirectory(targetPath, path, AVMConstants.DIR_APPBASE); + + // tag the store with the store type + this.avmService.setStoreProperty(stagingStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_STAGING_PREVIEW), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(previewStore); + + + // tag all related stores to indicate that they are part of a single sandbox + String sandboxIdProp = AVMConstants.PROP_SANDBOXID + GUID.generate(); + this.avmService.setStoreProperty(stagingStore, + QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + this.avmService.setStoreProperty(previewStore, + QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + } + + /** + * Create a user sandbox for the named store. + * + * A user sandbox is comprised of two stores, the first named 'storename-username-main' layered + * over the staging store with a preview store named 'storename-username-preview' layered over + * the main store. + * + * Various store meta-data properties are set including: + * Identifier for store-types: .sandbox.author.main and .sandbox.author.preview + * Store-id: .sandbox-id. (unique across all stores in the sandbox) + * DNS: .dns. = + * + * @param name The store name to create the sandbox for + * @param username Username of the user to create the sandbox for + */ + private void createUserSandbox(String name, String username) + { + // create the user 'main' store + String userStore = name + '-' + username + AVMConstants.STORE_MAIN; + this.avmService.createAVMStore(userStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + userStore); + + // create a layered directory pointing to 'appBase' in the staging area + String path = userStore + ":/"; + String targetPath = name + AVMConstants.STORE_STAGING + ":/" + AVMConstants.DIR_APPBASE; + this.avmService.createLayeredDirectory(targetPath, path, AVMConstants.DIR_APPBASE); + + // tag the store with the store type + this.avmService.setStoreProperty(userStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_AUTHOR_MAIN), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(userStore); + + + // create the user 'preview' store + String previewStore = name + '-' + username + AVMConstants.STORE_PREVIEW; + this.avmService.createAVMStore(previewStore); + if (logger.isDebugEnabled()) + logger.debug("Created staging sandbox store: " + previewStore); + + // create a layered directory pointing to 'appBase' in the user 'main' store + path = previewStore + ":/"; + targetPath = userStore + ":/" + AVMConstants.DIR_APPBASE; + this.avmService.createLayeredDirectory(targetPath, path, AVMConstants.DIR_APPBASE); + + // tag the store with the store type + this.avmService.setStoreProperty(previewStore, + QName.createQName(null, AVMConstants.PROP_SANDBOX_AUTHOR_PREVIEW), + new PropertyValue(DataTypeDefinition.TEXT, null)); + + // tag the store with the DNS name property + tagStoreDNSPath(previewStore); + + + // tag all related stores to indicate that they are part of a single sandbox + String sandboxIdProp = AVMConstants.PROP_SANDBOXID + GUID.generate(); + this.avmService.setStoreProperty(userStore, QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + this.avmService.setStoreProperty(previewStore, QName.createQName(null, sandboxIdProp), + new PropertyValue(DataTypeDefinition.TEXT, null)); + } + + /** + * Tag a named store with a DNS path meta-data attribute. + * The DNS meta-data attribute is set to the system path 'store:/appBase/avm_webapps' + * + * @param store Name of the store to tag + */ + private void tagStoreDNSPath(String store) + { + String path = store + ":/" + AVMConstants.DIR_APPBASE + '/' + AVMConstants.DIR_WEBAPPS; + // TODO: DNS name mangle the property name - can only contain value DNS characters! + String dnsProp = AVMConstants.PROP_DNS + store; + this.avmService.setStoreProperty(store, QName.createQName(null, dnsProp), + new PropertyValue(DataTypeDefinition.TEXT, path)); } } diff --git a/source/web/images/icons/sandbox.gif b/source/web/images/icons/sandbox.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a5543211867ab4a645ed955602fdb5fa6eae058 GIT binary patch literal 1039 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 i&NS16(n10Wv~kDucbH + +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> +<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> + +<%@ page buffer="64kb" contentType="text/html;charset=UTF-8" %> +<%@ page isELIgnored="false" %> + + + + + <%-- load a bundle of properties with I18N strings --%> + + + + + <%-- Main outer table --%> + + + <%-- Title bar --%> + + + + + <%-- Main area --%> + + <%-- Shelf --%> + + + <%-- Work Area --%> + + +
+ <%@ include file="../parts/titlebar.jsp" %> +
+ <%@ include file="../parts/shelf.jsp" %> + + + <%-- Breadcrumb --%> + <%@ include file="../parts/breadcrumb.jsp" %> + + <%-- Status and Actions --%> + + + + + + + <%-- separator row with gradient shadow --%> + + + + + + + <%-- Details - Staging sandbox --%> + + + + + + + <%-- Details - User sandboxes --%> + + + + + + + <%-- Error Messages --%> + + + + + + + <%-- separator row with bottom panel graphics --%> + + + + + + +
+ + <%-- Status and Actions inner contents table --%> + <%-- Generally this consists of an icon, textual summary and actions for the current object --%> + + + + + +
+ + <%-- Summary --%> +
+
+
+
+ +
+ + + <%-- Staging Sandbox Info here --%> + ---STAGING SANDBOX INFO HERE--- + + + +
+ + + + <%-- User Sandboxes List --%> + ---USER SANDBOXES HERE--- + + + +
+ <%-- messages tag to show messages not handled by other specific message tags --%> + +
+
+ +
+ +
+ +