You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by so...@apache.org on 2008/03/20 07:37:10 UTC

svn commit: r639174 - in /lenya/branches/revolution/1.3.x: ./ src/java/org/apache/lenya/cms/content/flat/ src/java/org/apache/lenya/cms/content/hierarchical/ src/webapp/lenya/modules/edit/ src/webapp/lenya/modules/live/ src/webapp/lenya/modules/relate/

Author: solprovider
Date: Wed Mar 19 23:37:09 2008
New Revision: 639174

URL: http://svn.apache.org/viewvc?rev=639174&view=rev
Log:
Added Structure Editor interface. (Does not save.)

Added:
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/hierarchical.html
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xmap
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xml
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structure.xsl
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structures.xsl
Modified:
    lenya/branches/revolution/1.3.x/13DONE.txt
    lenya/branches/revolution/1.3.x/13TODO.txt
    lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java
    lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/SitetreeGenerator.java
    lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/hierarchical/HierarchicalResource.java
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/all.xsl
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/module.xmap
    lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/live/module.xmap

Modified: lenya/branches/revolution/1.3.x/13DONE.txt
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/13DONE.txt?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/13DONE.txt (original)
+++ lenya/branches/revolution/1.3.x/13DONE.txt Wed Mar 19 23:37:09 2008
@@ -1,10 +1,14 @@
 This file contains completed entries from the TODO file with the most recent entries at the top.  Separate Commits with "---".
 ======
 
+--- 
+DONE 20080319
+Structure editor/"relate" Module - Add Resources and move branches to new parent or root independent of translations.  Collapse/Expand tree.  Undo abilities.  Added link from Edit screen.
+
 ---
 -- DONE 20080308
 1.2 Authoring: Uses {pub}/xslt/page2xhtml.xsl.  lenya-body aggregate returns xhtml:html/xhtml:body rather than expected xhtml:html/xhtml:div[@id='body'].  Added former match to page2xhtml.xsl.
-Indexer: creating or updating Resources runs Indexer. Added system so only one thread handles updates while other threads may request that the first thread run update again.
+Indexer: creating or updating Resources runs Indexer. Added system so only one thread handles updates while other threads may request that the first thread run update again. IMPLEMENTATION: Queue background indexing. Thread check next index. Send changes to indexes with return of needsIndexing so add to queue. If exists and does not need updating, return
 Patched xhtml module.xmap during testing.
 Replace all ResourceExists Actions with the ResourceExists Selector in Modules.
 New Module requires and passes successful requests to Edit Module.

Modified: lenya/branches/revolution/1.3.x/13TODO.txt
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/13TODO.txt?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/13TODO.txt (original)
+++ lenya/branches/revolution/1.3.x/13TODO.txt Wed Mar 19 23:37:09 2008
@@ -1,12 +1,22 @@
-=================================================
-==== Needed to be function complete with 1.2 ====
-=================================================
----- Structure editor ----
-Admin screen: Structure editor
-Create new structure.  Copy existing.  Add Resources not in structure.  Move Resource to new parent or root.
-Careful: must keep Resource even if does not exist in current language.  Show greyed, but still allow move.
+====================
+==== Structures ====
+====================
+NOTE: Goal is to add "Save" action to Structure Editor.  [I will be implementing this next. - solprovider]
+
+- Move Index Configuration to Modules.  Allow both module.xml and separate files.  (module.xml requires work when inherited.  Separate files are automatically inherited.)
+- Read index configuration for names of Structures.  IndexConfiguration includes Structure and Revision names.  Load during initialization for use in adminstration.
+- Generator for names of Structures.
+- Create Design Resources.  Exclude Design Resources from "all" Index.
+- ModuleSourceFactory: Check for Design Resource before file system.
+Design resources: Module protocol can check datastore for design elements such as XSLT and CSS.  This is the reason for named resources; use UNID = publication + module + filepath.  Also useful for structures.
+- Move Structures to Design Resources.
+- "relate" Module: Change Editor to retrieve Structure as Design Resource.  Revisions, choose "live".
+- Implement "Save Resource" with run Indexer.
+
+==================
+==== Security ====
+==================
 
----- Security -----
 Resource-level Security.
 Access Control List in Resource.xml
 "admin" Group bypasses security and is allowed to do anything.
@@ -16,11 +26,13 @@
 "Does not exist" returns same Sorry page.
 Sorry: This resource is not available, either it does not exist or you do not have access to it.  (Link to Login page if not logged in.)
 DESIGN: How to handle inheritance?  Multiple parents?  Assume "live" structure?
+Workflow: Reproduce Lenya-1.2's approve/publish system.
 
+==============================================
+==== Links and i18n - Editor and Handling ====
+==============================================
 
-=====================================
-==== Links - Editor and Handling ====
-=====================================
+BUG?: Remove Attributes.removeAttribute from i18nTransformer.translateAttributes().
 
 Add "Choose Lenya doc link" dialog to Xinha.
 Add "Create file resource" to Xinha.
@@ -58,6 +70,7 @@
 Edit-Save must clear Cache. (Or "cache" Module must check if Resource is still valid.)
 
 New: ID Validation - No duplicates, periods, exclamation marks, or underscores.
+New: UNID Validation - No < and >. Must be valid directory name (deny :!,?*_"&+#/\| and leading .~).
 
 flat Module: content3.xsl sets doctype.  Need to use rules in {pub}/parameter-doctype.xmap
 Migration: Copy XSLTs to proper modules and patch as needed.
@@ -89,6 +102,14 @@
 
 Check synchronization of HashMaps.
 
+"relate" Module/Structure Editor: 
+- Add Categories (placeholder for menu entries with no document) using quotes to distinguish from UNIDs.  
+- Search other Revisions for Title when no "live" Revision or "live" Title is blank.  
+- Add "Copy Resource and all descendants" action.
+- Add export/import to assist copying amongst Structures.
+- Filter Resources on Types.
+
+
 =============================
 ==== ToDo List from 2006 ====
 =============================
@@ -96,13 +117,6 @@
 === 1.2.x Conversion
 Session Module: login.xsp -> NullPointerException
 
-
-Rethink structures.  
-Need "live" or "homepage"?.  Rename livemenu to live?  What variations are useful?
-All = all relations, use for authoring
-Live = use for menus.  Do not include /index.
-StructureEditor should use "visible in menu" flag to build "live".  Checkboxes on Structure editor.
-
 === Admin Screens
 Admin screen: Navigation between User/Group maintenance and Site maintenance.
 
@@ -121,16 +135,11 @@
 Filter by type?  doctype?  IndexPart?
 URLs: Use a Structure?  All flat (UNIDs)?  Choice?  (I dislike UNIDs in URLs, but a Structure limits the results to what it contains.)
 
-
 =======================
 ====  Enhancements ====
 =======================
 [This section lists new abilities not required to complete 1.2 functionality.]
 
-Optimize Indexer.  Only run for language changed.
-
-Move structures to Resources so editing uses revision control.
-
 cocoon: protocol does not follow Module inheritance for missing files. Example: /pub/home/parameters should use /pub/xhtml/parameters if modules/home/module.xmap is missing.  Needing module.xmap defeats purpose of inheritance.  (module: protocol follows inheritance so resource-exists works as test for Module.)
 
 Identifier must not contain period, underscore, or exclamation mark.  Allow spaces? Caps?
@@ -142,10 +151,7 @@
 Check {pub} directory for publication.xml.
 Module to clean migrated publications: copy content, modules, security. For content, fix type and remove doctype. Move publication.xml to {pub}.
 
-Admin screens: Resource - Update structures if "id" has changed.
-
-Design resources: Module protocol can check datastore for design elements such as XSLT and CSS.  This is the reason for named resources; use UNID = publication + module + filepath.  Also useful for structures.
-
+Admin screens: Resource: Change ID - Must Update structures and run Indexer.
 
 Move CreateResourceTransformer and CreateRevisionTransformer to content package with implementation code in content.flat.
 
@@ -153,11 +159,7 @@
 
 publication:name - should return name, currently stored in publication.xml.  Why?  Move to publication.xconf?  Must be available from Publication.java and PublicationModule.java
 
-
-Resource: Active dates: start, expire
-Careful: All children will disappear from Index when parent is deactivated.
-
-Resources: Deleting index kills a structure.  Maintain Structures as Resources with automatic versioning for easy rollback.
+Resource: Active dates: start, expire. Careful: All children will disappear from Index when parent is deactivated.
 
 Admin screen: User/Group editor
 
@@ -171,6 +173,7 @@
 
 Editor: Fix tables.  Is there a better plugin?
 
+JCR/Jackrabbit datastore.
 
 == FlatIndexPart
 Parse using / forcing begining, * for any element, and // for any number of elements 
@@ -178,16 +181,13 @@
 Example: token = "/*/*" must be second level
 Example: token = "//xml/file" must be file under xml, but xml can be at any level.
 
-
 == Indexer
-Pull confs from Modules.
-Queue background indexing.
-Thread check next index.
-Send changes to indexes with return of needsIndexing so add to queue.
-If exists and does not need updating, return
+Indexer should only update dependent Indexes when a Structure is saved.
+
+Optimize Indexer to only run for language changed.
+
 If exists and needs updating, check update freq.  If cache-and-update (assume true), start new thread for update.
 Match identical indexconfs, same filters.  ?superset include unless different value for same name.  Could cause issues if poor code copies extra attributes.
-
 
 === 1.3.1
 build/lenya directory should be self-contained runnable.

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java Wed Mar 19 23:37:09 2008
@@ -230,6 +230,22 @@
             String value = resource.get(part.getProperty());
             if(value.length() > 0) element.setAttribute(part.getName(), value);
          }
+         // Add translations with language and title.
+         String[] languages = resource.getLanguages();
+         for(int l = 0; l < languages.length; l++){
+            Element translationElement = addElement(document, element, "translation");
+            translationElement.setAttribute("language", languages[l]);
+            FlatTranslation translation = resource.getTranslation(languages[l], false);
+            if(null != translation){
+               FlatRevision revision = translation.getRevision();
+               if(null != revision){
+                  String title = revision.getTitle();
+                  if(title.length() > 0){
+                     translationElement.setAttribute("title", title);
+                  }
+               }
+            }
+         }
          // INCLUDE - END
       } // for
    }

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/SitetreeGenerator.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/SitetreeGenerator.java?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/SitetreeGenerator.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/SitetreeGenerator.java Wed Mar 19 23:37:09 2008
@@ -64,7 +64,7 @@
          if(pub.getContentType().equalsIgnoreCase(Content.TYPE_FLAT)){
             this.inputSource = super.resolver.resolveURI(pub.getContent().getIndexFilename(src, language));
          }else{
-            // Lenya-1.2
+            // Lenya-1.2 Hierarchical Content 
             File testfile = new File(pub.getContentDirectory(), src + File.separator + "sitetree.xml");
             if(!testfile.exists())
                testfile = new File(pub.getContentDirectory(), "live" + File.separator + "sitetree.xml");
@@ -139,13 +139,5 @@
    // module = uri.substring(pos);
    // }
    // return module;
-   // }
-   // private Publication getPublication(String publication, String servletContextPath) {
-   // try{
-   // return PublicationFactory.getPublication(publication, servletContextPath);
-   // }catch(org.apache.lenya.cms.publication.PublicationException pe){
-   // System.out.println("PNF: " + publication + " not found.");
-   // return (Publication) null;
-   // }
    // }
 }

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/hierarchical/HierarchicalResource.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/hierarchical/HierarchicalResource.java?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/hierarchical/HierarchicalResource.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/hierarchical/HierarchicalResource.java Wed Mar 19 23:37:09 2008
@@ -21,7 +21,6 @@
    private String id;
    private String area;
    public HierarchicalResource(File contentDirectory, String unid) {
-      System.out.println("HierarchicalResource UNID=" + unid);
       this.contentDirectory = contentDirectory;
       Location location = new Location(unid);
       id = location.getUnid();

Modified: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/all.xsl
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/all.xsl?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/all.xsl (original)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/all.xsl Wed Mar 19 23:37:09 2008
@@ -27,8 +27,10 @@
 <h1><xsl:value-of select="$publication"/>&#160;<i18n:text>Resources</i18n:text></h1>
 <xsl:if test="string-length($new) &gt; 0">
 <xsl:element name="a">
-<xsl:attribute name="href">/<xsl:value-of select="$publication"/>/<xsl:value-of select="$new"/></xsl:attribute>Create Resource</xsl:element>
+<xsl:attribute name="href">/<xsl:value-of select="$publication"/>/<xsl:value-of select="$new"/></xsl:attribute>Create Resource</xsl:element>&#160;
 </xsl:if>
+<xsl:element name="a">
+<xsl:attribute name="href">/<xsl:value-of select="$publication"/>/relate</xsl:attribute>Edit Structures</xsl:element>
 <table border="1">
 <tr>
 <th><i18n:text>UNID</i18n:text></th>

Modified: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/module.xmap
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/module.xmap?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/module.xmap (original)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/edit/module.xmap Wed Mar 19 23:37:09 2008
@@ -12,12 +12,6 @@
                   <map:parameter name="module" value="{module:module}"/>
                   <map:parameter name="publicationname" value="{publication:name}"/>
                   <map:parameter name="publicationlanguages" value="{publication:languages}"/>
-                  <map:select type="resource-exists">
-                     <map:when test="module://new/module.xmap">
-                        <map:parameter name="new" value="new"/>
-                     </map:when>
-                  </map:select>
-<!-- BUG: Selector does not work.  -->
                   <map:parameter name="new" value="new"/>
                </map:transform>
                <map:transform type="i18n"/>           

Modified: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/live/module.xmap
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/live/module.xmap?rev=639174&r1=639173&r2=639174&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/live/module.xmap (original)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/live/module.xmap Wed Mar 19 23:37:09 2008
@@ -27,7 +27,7 @@
             </map:match>
 <!-- Default -->
             <map:generate src="module://lenya/sorry.xml"/>
-            <map:serialize type="html"/>
+            <map:serialize type="html" status-code="404"/>
          </map:match>
       </map:pipeline>
    </map:pipelines>

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/hierarchical.html
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/hierarchical.html?rev=639174&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/hierarchical.html (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/hierarchical.html Wed Mar 19 23:37:09 2008
@@ -0,0 +1,9 @@
+<HTML>
+<HEAD>
+<TITLE>Error</TITLE>
+</HEAD>
+<BODY>
+<H1>Error</H1>
+The Relations Module cannot be used with Hierarchical Content.  The Authoring Module is intended for Hierarchical Content, but it was not found.  If the Content is Flat (such as after using the "flat" migration Module), please change the content setting in {pub}/config/publication.xconf, and then restart Lenya to build the Indexes.
+</BODY>
+</HTML>
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xmap
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xmap?rev=639174&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xmap (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xmap Wed Mar 19 23:37:09 2008
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Relate Module -->
+<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
+
+   <map:resources>
+      <map:resource name="default">
+<!-- Default: Request does not specify anything after the slash. Choose Structure. -->
+<!-- TODO: Must be aware of Structure design elements in content -->
+              <map:generate type="directory" src="module:///../../pubs/{publication:publication}/content/relation">
+                  <map:parameter name="depth" value="1"/>
+               </map:generate>
+               <map:transform src="module:///structures.xsl">
+                  <map:parameter name="module" value="{module:module}"/>
+                  <map:parameter name="publication" value="{publication:publication}"/>
+                  <map:parameter name="publicationname" value="{publication:name}"/>
+               </map:transform>
+               <map:serialize type="xml"/>
+      </map:resource>
+   </map:resources>
+
+  <!-- =========================== Pipelines ================================ -->
+   <map:pipelines>
+      <map:pipeline>
+         <map:match pattern="**">
+<!-- Verify flat content. -->
+            <map:select type="parameter">
+               <map:parameter name="parameter-selector-test" value="{publication:contenttype}"/>
+               <map:when test="flat">
+               </map:when>
+               <map:otherwise>
+                  <map:generate src="module:///hierarchical.html"/> 
+                  <map:serialize type="html"/>
+               </map:otherwise>
+            </map:select>
+            <map:match pattern="all">
+               <map:generate type="sitetree"/>
+               <map:serialize type="xml"/>
+            </map:match>
+<!-- Edit Structure. -->
+            <map:match pattern="{module:module}/">
+               <map:call resource="default"/>
+            </map:match>
+            <!-- module/structure -->
+            <map:match pattern="{module:module}/*">
+               <map:aggregate element="content">
+                  <map:part src="cocoon:/all"/>
+<!-- TODO: Move structures to content -->
+                  <map:part src="module:///../../pubs/{publication:publication}/content/relation/{1}.xml"/>
+               </map:aggregate>
+               <map:transform src="module:///structure.xsl">
+                  <map:parameter name="module" value="{module:module}"/>
+                  <map:parameter name="name" value="{1}"/>
+                  <map:parameter name="publication" value="{publication:publication}"/>
+                  <map:parameter name="publicationname" value="{publication:name}"/>
+               </map:transform>
+               <map:transform type="i18n"/>
+               <map:serialize type="html"/>
+            </map:match>
+            <map:call resource="default"/>
+         </map:match>
+      </map:pipeline>
+   </map:pipelines>
+</map:sitemap>

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xml
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xml?rev=639174&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xml (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/module.xml Wed Mar 19 23:37:09 2008
@@ -0,0 +1,4 @@
+<module id="relate" name="Relations" minimum="1.3" created="1.3" content="flat">
+   <recommended id="edit">Allow editing of Resources.</recommended>
+   <description>Administration Page Module for editing Structures to specify relations amongst Resources.</description>
+</module>
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structure.xsl
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structure.xsl?rev=639174&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structure.xsl (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structure.xsl Wed Mar 19 23:37:09 2008
@@ -0,0 +1,672 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:xhtml="http://www.w3.org/1999/xhtml"
+    xmlns:page="http://apache.org/cocoon/lenya/cms-page/1.0"
+    xmlns:lenya="http://apache.org/cocoon/lenya/page-envelope/1.0" 
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:dcterms="http://purl.org/dc/terms/"
+    xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
+    exclude-result-prefixes="page xhtml"
+>
+
+<xsl:param name="publication"/>
+<xsl:param name="module"/>
+<xsl:param name="name"/>
+<xsl:param name="publicationname"/>
+<xsl:param name="publicationlanguages"/>
+
+<xsl:template match="/content">
+  <html>
+    <head>
+      <title><xsl:value-of select="$publication"/>&#160;<xsl:value-of select="$name"/>&#160;<i18n:text>Structure</i18n:text></title>
+<style type="text/css">
+h1{
+   margin: 0 0 5px 0;
+}
+h2{
+   margin: 10px 0 5px 0;
+}
+h3{
+   margin: 0 0 5px 0;
+}
+ol,ul{
+   margin: 0 10px 5px 20px;
+}
+#undo{
+   float: right;
+}
+#legend{
+   clear: both;
+   margin: 0px 0 10px 0;
+}
+#all{
+   float: left;
+   clear: left;
+   width: 40%;
+   margin: 0 10px 0 20px;
+}
+#structure{
+   float: right;
+   width: 55%;
+   margin: 0px 0px 10px 0px;
+}
+#information{
+   clear: left;
+   width: 40%;
+   border: solid 2px #FFCC33;
+   margin: 20px 0px 0 0;
+}
+#instructions{
+   clear: both;
+   border: solid 1px #000000;
+   margin: 20px 0px 0 0;
+   padding: 0px 10px 5px 10px;
+}
+.normal{
+   display: inline;
+}
+.orphan{
+   background-color: #FFFF66; 
+   display: inline;
+}
+.duplicate{
+   background-color: #FFCCCC; 
+   display: inline;
+}
+.selected{
+   background-color: #CCCCCC; 
+   display: inline;
+}
+.selectedtree{
+   background-color: #EEEEEE; 
+   display: inline;
+}
+.container{
+   margin: 0 0px 0 20px;
+   border-left: 1px dotted #CCCCCC;
+}
+.delete{
+   color: white;
+   text-decoration: none;
+   background-color: #CC0000; 
+   margin: 0 0px 0 10px;
+   font-size: smaller;
+   display: inline;
+   padding: 2px;
+}
+.expand{
+   color: black;
+   text-decoration: none;
+   background-color: #33FF33; 
+   margin: 10px 10px 10px 0px;
+   font-size: smaller;
+   display: inline;
+   line-height: 180%;
+   padding: 2px;
+}
+.rootsibling{
+   color: black;
+   text-decoration: none;
+   background-color: #FFCC33; 
+   margin: 0 10px 0 20px;
+   font-size: smaller;
+   display: inline;
+}
+.sibling{
+   color: black;
+   text-decoration: none;
+   background-color: #FFCC33; 
+   margin: 10px 10px 10px 0px;
+   font-size: smaller;
+   display: inline;
+   line-height: 180%;
+   padding: 2px;
+}
+.child{
+   color: black;
+   text-decoration: none;
+   background-color: #FFCC33; 
+   margin: 10px 10px 10px 0px;
+   font-size: smaller;
+   display: inline;
+   line-height: 180%;
+   padding: 2px;
+}
+.undo{
+   background-color: #CC0000; 
+   margin: 0 10px 0 0px;
+   font-size: smaller;
+   display: inline;
+   padding: 2px;
+}
+.undo a{
+   color: white;
+   text-decoration: none;
+}
+.redo{
+   background-color: #00CC00; 
+   margin: 0 10px 0 0px;
+   font-size: smaller;
+   display: inline;
+   padding: 2px;
+}
+.redo a{
+   color: white;
+   text-decoration: none;
+}
+
+</style>
+
+<script language="JavaScript">
+// Configuration
+MAX_UNDOS = 5;
+START_COLLAPSED = false;
+
+// StringBuffer
+function StringBuffer(){ this.buffer = []; }
+StringBuffer.prototype.append = function append(string){
+   this.buffer.push(string);
+   return this;
+};
+StringBuffer.prototype.toString = function toString(){ return this.buffer.join(""); };
+// UndoStorage
+function UndoSystem(maximum){
+   this.store = new Array();
+   this.max = maximum;
+   this.current = 0;
+}
+<xsl:text disable-output-escaping="yes">
+UndoSystem.prototype.add = function add(string){
+   if((this.current &gt; 1) &amp;&amp; (this.current &lt; this.store.length)) this.store.length = this.current;
+   if(this.current &gt; this.max){
+      this.store.splice(0, 1);
+   }else{
+      this.current++;
+   }
+   this.store.push(string);
+}
+UndoSystem.prototype.undo = function undo(increment){
+   this.current -= increment;
+   if(this.current &lt; 1) this.current = 1;
+   return this.store[this.current - 1];
+}
+UndoSystem.prototype.redo = function redo(increment){
+   this.current += increment;
+   if(this.current &gt; this.store.length) this.current = this.store.length;
+</xsl:text>
+   return this.store[this.current -1 ];
+}
+UndoSystem.prototype.getSize = function getSize(){
+   return this.store.length;
+}
+UndoSystem.prototype.getCurrent = function getCurrent(){
+   return this.current;
+}
+
+// Init
+var selected = "";
+var selectedInstance = 0;
+var allCount = 0;
+var unids = [];
+var allResources= new Object();
+var allType = new Object();
+var allId = new Object();
+var used = new Object();
+var structure = new StringBuffer();  // Changes to String after initialization
+var undos = new UndoSystem(MAX_UNDOS);
+var collapsed = new Object();
+var forceCollapse = START_COLLAPSED;
+// All
+<xsl:apply-templates select="index" mode="js"/>
+
+// Structure
+// &lt; begin children, &gt; end children
+<xsl:apply-templates select="resources" mode="js"/>
+
+undos.add('!0!' + structure);
+// Display Functions
+function drawUndo(){
+   number = undos.getSize();
+   current = undos.getCurrent();
+<xsl:text disable-output-escaping="yes">
+   if(2 &gt; number) return;
+   buffer = new StringBuffer();
+   for(u = current - 1; u &gt; 0; u--){
+      buffer.append('&lt;div class="undo"&gt;&lt;a href="javascript:undo(' + u + ');"&gt;UNDO ' + u + '&lt;a&gt;&lt;/div&gt;');
+   }
+   for(u = 1; u &lt;= (number - current); u++){
+      buffer.append('&lt;div class="redo"&gt;&lt;a href="javascript:redo(' + u + ');"&gt;REDO ' + u + '&lt;a&gt;&lt;/div&gt;');
+   }
+   undoDiv = getElementForId("undo");
+   undoDiv.innerHTML = buffer.toString();
+
+}
+function getSpan(unid, useUsed, inSelection, level){
+   // Decide class
+   className = 'normal';
+   usedCount = 0;
+   if(used[unid]) usedCount = used[unid];
+   if(unid == selected){
+      if(useUsed){
+         if(usedCount == selectedInstance){
+            className= 'selected';
+         }else{
+            className= 'selectedtree';
+         }
+      }else{
+         if(selectedInstance == 0){
+            className = 'selected';
+         }else{
+            className = 'selectedtree';
+         }
+      }
+   }else{
+      if(inSelection != -1){
+         className = 'selectedtree';
+      }else{
+         if(usedCount &gt; 2) usedCount = 2;
+         switch(usedCount){
+            case 0:
+               className ='orphan';
+               break;
+            case 1:
+                break;
+            case 2:
+               className ='duplicate';
+               break;
+            // default:
+         }
+      }
+   }
+   // Build String
+   buffer = new StringBuffer();
+//   for(i = 0; i &lt; level; i++){
+//       buffer.append('&#160;&#160;&#160;&#160;');
+//   }
+   buffer.append('&lt;div class="'+ className+ '"&gt;');
+   buffer.append('&lt;a href="javascript:select(\'' + unid);
+   if(useUsed){
+      buffer.append('!'+ used[unid]);
+   }
+   buffer.append('\');"&gt;' + allId[unid] + '&lt;a&gt; (' + allType[unid] + ')');
+   buffer.append('&lt;/div&gt;');
+   if(useUsed){
+      buffer.append('&lt;a href="javascript:remove(\'' + unid + '!'+ used[unid] +'\');" class="delete"&gt;Remove&lt;a&gt;');
+   }
+   return buffer.toString();
+</xsl:text>
+}
+
+function resetUsed(){
+   for(u in used){
+      used[u] = 0;
+   }
+}
+
+// #############################################################3
+function drawStructure(){
+   resetUsed();
+   structureString = structure.toString();
+   structureBuffer = new StringBuffer();
+<xsl:text disable-output-escaping="yes">
+   structureBuffer.append('&lt;a href="javascript:sibling(\'root\');" class="rootsibling"&gt;Sibling&lt;a&gt;&lt;br&gt;');
+   parts = new Array();
+   parts = structureString.split('&lt;');
+   siblings = new Array();
+   childs = new Array();
+   siblings.push("");
+   childs.push("");
+   level = -1;
+   inSelection = -1;
+   inCollapsed = -1;
+   unid ="root";
+   for(p in parts){
+      level++;
+      part = parts[p];
+      startName = 0;
+      if(part.charAt(startName) == '&gt;'){ // No children
+         if(-1 == inCollapsed){
+            structureBuffer.append(siblings.pop());
+            siblings.push("");
+            structureBuffer.append(childs.pop());
+         }
+      }else{
+         if("root" != unid){
+            if(forceCollapse) collapsed[unid + '!'+ used[unid]] = 1;
+            if(-1 == inCollapsed){
+               expandTitle = "Collapse";
+               if(collapsed[unid + '!'+ used[unid]]){
+                  expandTitle = "Expand";
+                  inCollapsed = level;
+               }
+               structureBuffer.append('&lt;a href="javascript:toggle(\'' + unid + '!'+ used[unid] +'\');" class="expand"&gt;'+expandTitle+'&lt;a&gt;');
+               if(-1 != inCollapsed){
+                  structureBuffer.append(siblings.pop());
+                  siblings.push("");
+                  childs.pop();
+               }
+            }
+         }
+         if(-1 == inCollapsed) structureBuffer.append(childs.pop());
+      }
+      while(part.charAt(startName) == '&gt;'){
+         level--;
+         startName++;
+         if(level &lt; inCollapsed){
+            inCollapsed = -1;
+         }
+         if(-1 == inCollapsed){
+            structureBuffer.append(siblings.pop());
+            structureBuffer.append('&lt;/div&gt;');
+         }
+      }
+      if(startName &lt; part.length){
+         unid = part.substring(startName);
+         used[unid]++;
+         if(level &lt;= inSelection){
+            inSelection = -1;
+         }
+         if((selected == unid) &amp;&amp; (used[unid] == selectedInstance)){
+           inSelection = level;
+         }
+         if(-1 == inCollapsed){
+            structureBuffer.append('&lt;div class="container"&gt;');
+            structureBuffer.append(getSpan(unid, true, inSelection, level) + '&lt;br&gt;');
+            if(-1 == inSelection){
+               siblings.push('&lt;a href="javascript:sibling(\'' + unid + '!'+ used[unid] +'\');" class="sibling"&gt;Sibling&lt;a&gt;');
+               childs.push('&lt;a href="javascript:child(\'' + unid + '!'+ used[unid] +'\');" class="child"&gt;Child&lt;a&gt;');
+            }else{
+               siblings.push("");  //Marks end of DIV for selected elements.  "&#160;" will force empty line, but looks silly.
+               childs.push("");
+            }
+         }
+</xsl:text>
+      }
+   }
+   structureDiv = getElementForId('structure');
+   structureDiv.innerHTML = structureBuffer.toString();
+   forceCollapse = false;
+}
+
+
+
+function drawAll(){
+   allBuffer = new StringBuffer();
+   for(u in unids){
+<xsl:text disable-output-escaping="yes">
+      allBuffer.append(getSpan(unids[u], false, -1, 0) + '&lt;br&gt;');
+   }
+</xsl:text>
+   allDiv = getElementForId('all');
+   allDiv.innerHTML = allBuffer.toString();
+}
+function redraw(){
+   drawStructure();
+   drawAll();
+   drawUndo();
+}
+function setInformation(string){
+   informationDiv = getElementForId("information");
+   informationDiv.innerHTML = string;
+}
+function select(key){
+   parts = key.split('!', 2);
+   selected = parts[0];
+   selectedInstance = 0;
+<xsl:text disable-output-escaping="yes">
+   if(parts.length &gt; 1) selectedInstance = parts[1];
+   setInformation('ID: ' + allId[selected] + '&lt;br&gt;Type: ' + allType[selected] + '&lt;br&gt;UNID: ' + selected + allResources[selected] + "&lt;br&gt;Appearances: " + used[selected]);
+   redraw();
+}
+function sibling(key){
+  move(key, 'sibling');
+}
+function child(key){
+  move(key, 'child');
+}
+function remove(key){
+   //oldSelected = selected;
+   //oldSelectedInstance = selectInstance;
+   parts = key.split('!', 2);
+   selected = parts[0];
+   selectedInstance = 0;
+   if(parts.length &gt; 1) selectedInstance = parts[1];
+   move('root', 'delete');
+   //selected = oldSelected;
+   selectedInstance = 0;
+   return;  // Some browsers navigate to return value if no return statement.
+}
+function move(key, action){
+   if(0 == selected.length){
+      setInformation('The requested action requires a Resource to be selected.');
+      return;
+   }
+   resetUsed();
+   parts = key.split('!', 2);
+   target = parts[0];
+   if(('root' == target) &amp;&amp; (0 == selectedInstance)) {
+      structure = selected + '&lt;&gt;' + structure;
+      redraw();
+      return;
+   }
+   targetInstance = 0;
+   if(parts.length &gt; 1) targetInstance = parts[1];
+   selection = new StringBuffer();
+   beforeTarget = new StringBuffer();
+   afterTarget = new StringBuffer();
+   structureString = structure.toString();
+   parts = new Array();
+   parts = structureString.split('&lt;');
+   level = -1;
+   inSelection = -1;
+   inTarget = -1;
+   if('root' == target){
+      inTarget = -2;
+   }
+   if(0 == selectedInstance){
+      selection.append(selected + '&lt;&gt;');
+   }
+   for(p in parts){
+      if(-1 != level){
+         if(-1 == inSelection){
+            if(-2 == inTarget){
+               afterTarget.append('&lt;');
+            }else{
+               beforeTarget.append('&lt;');
+               if(('child' == action) &amp;&amp; (inTarget &gt; -1)){
+                  inTarget = -2;
+               }
+            }
+         }else{
+            selection.append('&lt;');
+         }
+      }
+      level++;
+      part = parts[p];
+      startName = 0;
+      while(part.charAt(startName) == '&gt;'){
+         if(-1 == inSelection){
+            if(-2 == inTarget){
+               afterTarget.append('&gt;');
+            }else{
+               beforeTarget.append('&gt;');
+            }
+         }else{
+            selection.append('&gt;');
+         }
+         level--;
+         if(level &lt;= inSelection){
+            inSelection = -1;
+         }
+         if(level &lt;= inTarget){
+            inTarget = -2;
+         }
+         startName++;
+      }
+      if(startName &lt; part.length){
+         unid = part.substring(startName);
+         used[unid]++;
+         if((selected == unid) &amp;&amp; (used[unid] == selectedInstance)){
+           inSelection = level;
+         }
+         if((target == unid) &amp;&amp; (used[unid] == targetInstance)){
+           inTarget = level;
+         }
+         if(inSelection == -1){
+            if(inTarget == -2){
+               afterTarget.append(unid);
+            }else{
+               beforeTarget.append(unid);
+            }
+         }else{
+            selection.append(unid);
+         }
+      }
+   }
+   if('delete' == action){
+      structure = beforeTarget.toString() + afterTarget.toString();
+   }else{
+      structure = beforeTarget.toString() + selection.toString() + afterTarget.toString();
+   }
+   undos.add(selected + '!' + selectedInstance + '!' + structure);
+   // Collapses are saved by position which may not be accurate after changing the structure
+   // if a Resource is moved before or after an entry for the same Resource and only one is collapsed 
+   // expandAllFunction(); // Prevents issue but annoys user.
+   redraw();
+}
+function useUndo(string){
+   parts = string.split('!', 3);
+   if(3 != parts.length) return;
+   selected = parts[0];
+   selectedInstance = parts[1];
+   structure = parts[2];
+   redraw();
+}
+function undo(increment){
+   useUndo(undos.undo(increment));
+}
+function redo(increment){
+   useUndo(undos.redo(increment));
+}
+function toggle(key){
+   if(collapsed[key]){
+      delete collapsed[key];
+   }else{
+      collapsed[key] = 1;
+   }
+   drawStructure();
+}
+function expandAllFunction(){
+   for(c in collapsed) delete collapsed[c];
+}
+function expandAll(){
+   expandAllFunction();
+   drawStructure();
+}
+function collapseAll(){
+   forceCollapse = true;
+   drawStructure();
+}
+
+// ## Helper Functions
+function addUsed(unid){
+   if(used[unid]){
+      used[unid]++;
+   }else{
+      used[unid] = 1;
+   }
+}
+function getElementForId(id){
+   if(document.getElementById) return document.getElementById(id);
+   if(document.all) return document.all(id);
+   if(document.layers) return document.layers(id);
+}
+</xsl:text></script>
+    </head>	
+    <body>
+<div id="undo">&#160;</div>
+<h1><xsl:value-of select="$publication"/>&#160;<xsl:value-of select="$name"/>&#160;<i18n:text>Structure</i18n:text></h1>
+<div id="legend">
+<!-- TODO: use i18n for labels. -->
+<div class="normal"> NORMAL </div>
+<div class="orphan"> ORPHAN </div>
+<div class="duplicate"> DUPLICATE </div>
+<div class="selected"> SELECTED </div>
+<div class="selectedtree"> SUBTREE </div>
+<div class="expand"><a href="javascript:expandAll();">Expand All</a></div>
+<div class="expand"><a href="javascript:collapseAll();">Collapse All</a></div>
+
+</div>
+<div id="all">This editor requires JavaScript.  If you are seeing this message:<ul>
+<li>The Structure is very large. Please wait.</li>
+<li>JavaScript is disabled in the browser.</li>
+<li>JavaScript does not work properly in the browser.  (This editor was tested with Mozilla 1.7, Mozilla Firefox 2.0, and Microsoft Internet Explorer 6.0.)</li>
+<li>The computer is slow or busy doing something else.</li>
+</ul>
+</div>
+<div id="structure">&#160;</div>
+<div id="information">&#160;</div>
+<div id="instructions">
+<h2>Instructions</h2>
+This editor has 7 areas. <ol>
+<li>Title - Name of Publication and Structure being edited.</li>
+<li>Legend - Explanation of background colors<ul>
+<li>Normal - Resources appearing once and only once in the Structure.</li>
+<li>Orphan - Resources not appearing in the Structure and so only appears in All Resources.</li>
+<li>Duplicate - Resources appearing more than once in the Structure.  Select and check Information for the exact number.</li>
+<li>Selected - The current selection.</li>
+<li>Subtree - All resources that will move with the selection, and other appearances of the selected resource (which will not move unless under the selection.)</li>
+</ul></li>
+<li>All Resources - Clicking the ID chooses the resource to be ADDED.</li>
+<li>Information - Orange box describing the selected Resource including the Titles of existing Translations.</li>
+<li>Structure - Hierarchical list on right side.  Clicking an ID chooses a Resource (and all descendants) to be MOVED.  Includes most actions.</li>
+<li>Undo - Appears in upper right corner after an action.</li>
+<li>Instructions - Everything needed to use this editor.</li>
+</ol>
+<h3>Actions</h3><ul>
+<li>Remove - Removes the resource and all descendants from the Structure.</li>
+<li>Sibling - Adds or moves the selected Resource as a sibling of the parent Resource.</li>
+<li>Child - Adds or moves the selected Resource as a child of the parent Resource.</li>
+<li>Undo/Redo - Clicking an UNDO button will revert to a previous state and displays REDO buttons.  Clicking a REDO button undoes the UNDO.  A new action removes the REDO buttons.</li>
+<li>Save - Saves the Structure and returns to the previous page.</li>
+<li>Cancel - Returns to the previous page without saving changes.</li>
+
+</ul>
+Note that Sibling and Child actions depend on where the selected Resource was clicked.  If the Resource was chosen from the All Resources list, the Resource will be ADDED.  If the Resource was chosen from the Structure list, the Resource and its descendants will be MOVED.  Copying a portion of the structure has not been implemented.
+</div>
+<script language="JavaScript">
+redraw();
+</script>
+</body></html>
+</xsl:template>
+
+<!-- All: JavaScript -->
+<xsl:template match="index" mode="js">
+<xsl:apply-templates select="resource" mode="js">
+   <xsl:sort select="@id"/>
+</xsl:apply-templates>
+</xsl:template>
+
+<xsl:template match="resource" mode="js">
+unids[allCount++] = "<xsl:value-of select="@unid"/>";
+used["<xsl:value-of select="@unid"/>"] = 0;
+allId["<xsl:value-of select="@unid"/>"] = '<xsl:value-of select="@id"/>';
+allType["<xsl:value-of select="@unid"/>"] = '<xsl:value-of select="@type"/>';
+allResources["<xsl:value-of select="@unid"/>"] = '<xsl:apply-templates select="translation" mode="js"/>';
+</xsl:template>
+
+<xsl:template match="translation" mode="js"><br/>&#160; &#160;<xsl:value-of select="@language"/>:<xsl:value-of select="@title"/></xsl:template>
+
+<!-- Structure: JavaScript -->
+<xsl:template match="resources" mode="js"><xsl:apply-templates select="resource" mode="structurejs"/></xsl:template>
+
+<xsl:template match="resource" mode="structurejs">
+addUsed("<xsl:value-of select="@unid"/>");
+structure.append("<xsl:value-of select="@unid"/><xsl:text disable-output-escaping="yes">&lt;</xsl:text>");
+<xsl:apply-templates select="resource" mode="structurejs"/>
+<xsl:text disable-output-escaping="yes">structure.append("&gt;");</xsl:text>
+</xsl:template>
+
+</xsl:stylesheet> 

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structures.xsl
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structures.xsl?rev=639174&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structures.xsl (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/relate/structures.xsl Wed Mar 19 23:37:09 2008
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:xhtml="http://www.w3.org/1999/xhtml"
+    xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
+    xmlns:dir="http://apache.org/cocoon/directory/2.0"
+    exclude-result-prefixes="dir xhtml"
+>
+
+<xsl:param name="publication"/>
+<xsl:param name="module"/>
+<xsl:param name="publicationname"/>
+<xsl:param name="publicationlanguages"/>
+
+<xsl:template match="/dir:directory">
+  <html>
+    <head>
+      <title><xsl:value-of select="$publication"/>&#160;<i18n:text>Structures</i18n:text></title>
+    </head>	
+    <body>
+<h1><xsl:value-of select="$publication"/>&#160;<i18n:text>Structures</i18n:text></h1>
+<xsl:apply-templates select="dir:file"/>
+</body></html>
+</xsl:template>
+
+<xsl:template match="dir:file">
+<xsl:variable name="structure"><xsl:value-of select="substring-before(@name, '.')"/></xsl:variable>
+<xsl:element name="a">
+<xsl:attribute name="href">/<xsl:value-of select="$publication"/>/<xsl:value-of select="$module"/>/<xsl:value-of select="$structure"/></xsl:attribute><xsl:value-of select="$structure"/></xsl:element>
+<br/>
+</xsl:template>
+
+
+</xsl:stylesheet> 



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org