Gallery Notes

Jan. 8, 2007

Set up an initial conflence page at Gallery Tool .
Correspondance with Daphne. She will create wire frames going forward.

Started initial research into RSF. Created a set of resource links.

The first step in getting RSF to work is to install the RSF maven pluging. Sadly, this command failed:

maven plugin:download -Dmaven.repo.remote=http:/
/www2.caret.cam.ac.uk/maven -DgroupId=caret -DartifactId=dependency-compile -Dve
rsion=1.0

With the following errors:

Attempting to download commons-jelly-tags-xml-20030211.142705.jar.
WARNING: Failed to download commons-jelly-tags-xml-20030211.142705.jar.
Attempting to download commons-jelly-tags-interaction-20030211.143817.jar.
WARNING: Failed to download commons-jelly-tags-interaction-20030211.143817.jar.

The build cannot continue because of the following unsatisfied dependencies:
commons-jelly-tags-xml-20030211.142705.jar (try downloading from http://jakarta.
apache.org/commons/jelly/libs/xml/)
commons-jelly-tags-interaction-20030211.143817.jar

I sent a message off to Antranig for some hints.

Feb. 20,2007

So my action handlers are being called correctly. They set a variable in the SequenceBean called seqAction: an integer ranging from 0 to 4. Zero is reserved for the default (no action) state. The handlers correctly set this value to the action they handle. However, when the SequenceProducer bean is invoked to create the sequence view component tree, and the SequenceBean is injected into it, it's a new insance of the bean. The value of seqAction has been reset to zero. I tried making SequenceBean a singleton, but that didn't help.

Jan. 9, 2007

Response from Antranig:

This isn't the RSF plugin, but the CARET "dependency compile plugin"
which isn't
necessary for working with RSF, but is helpful for working with it if you are
using a strategy of building from trunk, which isn't recommended especially
for
beginning users. Sorry that the Getting Started page doesn't make this more
clear - we are planning a big revamp of the RSF website starting from this
month.

I am not a Maven expert, but it sounds like the problem is something to do with
your Maven installation - it will be the plugin: task failing, not the plugin
itself. You could try clearing your plugin cache, if this doesn't work and you
really do want to keep working with an RSF source build, you could try
checking the plugin out from SVN at https://saffron.caret.cam.ac.uk/svn/projects/dependency-compile-plugin/trunk/
and then running "maven plugin:install" on it.

If not, you can just skip this step (probably best) and just work with RSF from
the released JARs (version 0.7 as of last month)

You'd probably be better off following Aaron's instructions from his bootcamp,
which are more tightly focused on needs of Sakai development.

http://bugs.sakaiproject.org/confluence/display/BOOT/Sakai+App+Builder

Note that the plugin is not yet updated to the 0.7 level of the RSF jars,
although the applications it generates will be compatible (I believe).

Jan. 11, 2007

Furthere word from Antranig:

I've investigated this problem in a bit more detail and it appears to be a fault that has developed with the ibiblio repository. Somehow for these jars (and generally not for others) it is returning an HTTP 301 for a "permanent redirect" to one of the mirrors, which the Maven client does not understand. The workaround is to manually specify a mirror which you know works correctly (I choose dotsrc as I recommend further down the page), so that the plugin download line looks as follows:

maven plugin:download
-Dmaven.repo.remote=http://www2.caret.cam.ac.uk/maven,http://mirrors.dotsrc.org/maven
-DgroupId=caret -DartifactId=dependency-compile -Dversion=1.0

I've updated the docs page accordingly.

Jan. 12, 2007

Working through the Programmer's Cafe workshop set up. Downloading all this code from India proved to be a bit challenging as the SVN kept timing out partway through. I had to manually work through each entry in the .externals file to download them. Created a new, clean copy of Tomcat and will build into it. Sakai-cafe built without error. Able to start Mecury and Charon without error.

Reading further into the Programmer's Cafe requires that I set up Sakai to use MySQL, import Sakai into Eclipse, download the app generated that Aaron built, and use it to generate the test cases. Frankly, this is a lot of work. I'm going to retreat to the startup processed recommended by Antranig on the RSF Wiki Site.

Installed the RSF plugin successfully. Antranig has changed the command such that it works now. Downloaded the numbers guessing game and installed it in Tomcat. It failed on startup. Will attempt to get the HelloWorld app and build it. It was not were it was purported to be, but at this instead:

https://saffron.caret.cam.ac.uk/svn/projects/RSFHelloWorld/trunk/

The maven commands for RSF projects are a bit daunting:

maven -Dprojectdir=J-RSFUtil -Dgoal=full dependencyCompile:goal -Dcaret.dependencyCompile.includes=*/project.xml,*/*/project.xml  

Antranig does have a windows script called "depit" that simlifies this. I may need to download and install it.

Although spring was successfully downloaded, the build failed:

BUILD FAILED
File...... C:\Documents and Settings\Mark\.maven\cache\dependency-compile-1.1\pl
ugin.jelly
Element... maven:reactor
Line...... 146
Column.... 9
The build cannot continue because of the following unsatisfied dependencies:

ponderutilcore-1.2.1-dev.jar
j-servletutil-1.2.1-dev.jar
rsfutil-0.7.1-dev.jar

Perhaps my repo path isn't right. Added more paths, but that didn't do it. I had a look at www2.caret.ac.uk/maven and noted that these jars are present, but do not have a -dev verison number. These version numbers come from the build.properties file in the RSFHelloWorld sources. I will try editing them out and see what happens.
Still fails, but the names seem to be correct. The artifactId seems to be correct as well. It should find and download these files.

The build.properties included with RSFHelloWorld now reads:

maven.repo.remote=http://mirrors.dotsrc.org/maven,http://www2.caret.cam.ac.uk/maven
maven.tomcat.home=C:/dev/apache-tomcat-5.5.17/
deploy.webappname=RSFHello
rsfutil.version=0.7.1
ponderutilcore.version=1.2.1
jservletutil.version=1.2.1

I have changed the location of maven.tomcat.home to be my location.
Now getting timeout exceptions, instead of can't download.
Attempted to download the JARS manually into local repository. They seemed to be downloaded ok, but project will still not build. Will try after deleting maven cache.
Still failing. Grr.

Ok, I got it to build. It was a combination of pilot error and wrong version numbers. I copied the RSFHelloWorld over into a separate directory, but didn't change where I was editing the verison numbers in the project.properties file. This file now reads:

maven.repo.remote=http://mirrors.dotsrc.org/maven,http://www2.caret.cam.ac.uk/maven
maven.tomcat.home=C:/dev/apache-tomcat-5.5.17/
deploy.webappname=RSFHello
rsfutil.version=0.7M1
ponderutilcore.version=1.2M1
jservletutil.version=1.2M1

These version numbers seem to line up better with what is on the caret/maven server, and they downloaded successfully.
Sadly, tomcat generated an ENOURMOUS number of errors on startup, most having to do with spring. Perhaps the versions numbers are still incorrect. I can try against the 1.2 and 0.7 versions of the JARs, I suppose.

I downloaded the sources of pondercoreutil, j-servletutil, and rsfutil. Low and behold, they use 1.2.1-dev as their version number. That was my mistake. I should have used one of the build tags instead of the trunk versions of the code.

I think I'm going to have an in-depth look at the hello world app and see if I can figure out how to get it into Sakai. See RSF Simple Tool.

Jan. 29, 2007

Having completed a number of RSF experiments, I've reached a basic understanding of using it as the presentation technology for the Gallery Tool. While I'm waiting on final wireframes from Daphne Ogle, there are number of things that can be prepared. Word from UCB is that the software will be kept in https://source.sakaiproject.org/conrib/ucb. I'll call the module "gallery".

Before getting in too deep, I ran a quick check of my development environment to see if the Resources Tool was functioning propertly. Oops! I get an error message indicating a databased failure. Looks like the RT doesn't work all that well with Hypersonic, though it could also be a failure on my part to configure my environment for it. MySQL is installed on this machine, so what I need to do is configure my Sakai development environment to use that instead.

Worked my way through Aaron's documentation on enabling MySQL for Sakai. No problems along the way. One of the configuration steps to to copy sakai.properties into tomcat and customize it for MySQL. On startup of tomcat, I get the following error:

ERROR: Failed to preinstantiate org.sakaiproject.content.api.ContentHostingService as a singleton. Destroying all spring beans.
(2007-01-29 12:37:12,750 main_org.springframework.context.support.SakaiApplicationContext$1)
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'org.sakaiproject.content.api.ContentHostingService' defined in file
\dev\apache-tomcat-5.5.17\components\sakai-content-pack\WEB-INF\components.xml:
Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException:
Invalid property 'prioritySortEnabled' of bean class org.sakaiproject.content.impl.DbContentService:
Bean property 'prioritySortEnabled' is not writable or has an invalid setter method:
Does the parameter type of the setter match the return type of the getter?
org.springframework.beans.NotWritablePropertyException:
Invalid property 'prioritySortEnabled' of bean class org.sakaiproject.content.impl.DbContentService:
Bean property 'prioritySortEnabled' is not writable or has an invalid setter method: Does the parameter type of the setter match the return type of the getter?

Sadly, my reading of this is that the most recent version of Content Hosting is not included in the Sakai Cafe distribution. In theory, I can swap in the 2.3 version, but if it has any dependencies, it will fail. Heck, let's give it a try. Well, sakai-cafe is just not building for me. I'm going to have to build the whole environment, I think, which is going to slow things down a fair bit, I think. Too a while, but I got the Sakai 2.3 environment to build. I had to remove OSP and rWiki before tomcat would start, however.

So Sakai comes up. I can create a test site and add the resource tool. On selecting the resource tool, I get a fatal error:

org.sakaiproject.tool.api.ToolException
at org.sakaiproject.cheftool.ToolServlet.doGet(ToolServlet.java:208)
caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
caused by: java.lang.NoClassDefFoundError: org/apache/xml/serialize/XMLSerializer
at org.sakaiproject.util.Xml.writeDocumentToString(Xml.java:223)

So it can't find the XMLSerializer. Why didn't maven bring this in? Incidentally, I saw this same error in sakai cafa, so the lack of whole environment wasn't the problem. This is part of the Xerxes package. I might not be getting the right verison of Xerces, which I think comes bundled in with tomcat.

Added Xerces by hand. I shouldn't have to do this. I suspect that it's presence in Sakai is a side effect of some other module bringing it in. Regardless, it seems to start up now. Created a Gallery-Test worksite. In it, created folder for Galleries. In that, a gallery called "Irish Ruins". Ten images were added from my collection of photographs, each with title and description. Looks like this in my Sakai environment:

Finding how to impose a priority order wasn't obvious to me, which will be a problem for students using this approach to order slides. You have to check the box on the left of "Irish Ruins", the click the "Reorder" link on it's right. This brings up a page to order the images by moving them up and down. Here is the final, ordered view of images:

This provides a test case to develop the gallery tool against.

Copied RsfTestBaser into sakai_2_3_0 and renamed it to "gallery". Attempted to build it with Maven. Failed, can't find ponderutilcore, j-servletutil, and rsfutil. Needed to download the version compatible with 0.7. Compiled and deployed. RsfTestBase comes up in mercury. Verified also that Resource Tool is retaining data.

Jan. 30, 2007

Changed names in the (former) RsfTestBase to gallery names. The maven artifactId is "gallery", the Sakai tool name is "sakai.gallery". Elminated all views except main. Simplified template content down to a hello world view. Renmaed HelloBean to GalleryService as a placeholder for a new gallery service. Eventually this will need to be moved off into it's own maven build per Sakai best practice. Built, deployed, it runs.

This is now a stubbed Gallery Tool application. It doesn't do much, but it's ready to evolve into do whatever Berkeley needs. While it displays in Mercury, this tool will need to have a tool placement and be resident in a site with hosted content. I added to the new gallery tool to my gallery test site. Had to use the "Sites" tool to add it, since the Gallery Tool didn't appear in "Worksite Setup". It looks like this in the Sakai portal:

Feb. 1, 2007

Started work on the GalleryService and associated objects. Defined an API. Update Gallery Design. The Service contains three classes:

  • GalleryService
  • ImageCollection
  • Image

Together, the should allow ContentCollections to serve as ImageCollections, and ContentResources as Images.

Feb. 2, 2007

Added getName(), getId(), getDescription(), and getUrl() to Image. This is just about all I need to create the initial Gallery Tool view.

I'm ready to start using RSF to generate the main view page (Gallery View). I'd like to be able to use the standard Sakai style sheets, but I don't really know how to use the shared CSS files. I tried adding them to the Gallery web app, but the only place I could get them to work was to include them as a sub-directory off template. This isn't really the right place for them.

Ok. I'm going to try again with a URL path of "/library/skin/default/". Actually, tool_base.css is in "/library/skin", while tool.css is in "/library/skin/default". The various folder icons should be in "/library/image/sakai/". Made the changes to main.html. They all worked.

Next step is to add a bundle file so that I can offload the strings to be included in the main view. MessageLocator bean was injected into the MainProducer correctly. Able to access messages using RSF-EL, such as "#{messageLocator.setup}".

Feb. 3, 2007

Expanded main view to include image collection navigation panel. Mostly working, but the names of the collections are not being displayed. Instead, they are numbered.
Found the problem. A simple cut and paste error from other code. Names of Image collections are now displayed.

The Gallery Tool is being displayed in a very short tool space. I'm unable to figure out how to give it more space.
According to Dr. Chuck:

mjnsakai: I' writing a new tool for Sakai.
csev@mac.com: Down here at the uPortal/code bash
csev@mac.com: Pluto 1.1
csev@mac.com: Wazzup?
mjnsakai: When I display it in Charon, the tool is shown in a very short iFrame.
mjnsakai: How do I increase the size of the frame?
csev@mac.com: You need to have the right stuff in the onlod of your iframe.
csev@mac.com: onload
csev@mac.com: There is a request parameter
mjnsakai: ah
csev@mac.com: That has the text to put in the onload
csev@mac.com: Hang on...
csev@mac.com: req.setAttribute("sakai.html.body.onload", bodyonload.toString());
mjnsakai: is this in a meta?
csev@mac.com: Grab that attribute from the request and say
csev@mac.com: <body onload="--- that stuff---">
csev@mac.com: When viewing source it will look like
mjnsakai: ok.
csev@mac.com: <body onload="parent.setmainframeheight('somexguidx');" )
csev@mac.com: It resizes the parent frame after load completes.
mjnsakai: sweet. (and obscure)
csev@mac.com: nah - read the tool doc in /reference/docs/architecture

From Sakai Tools:

To cooperate with the portal in HTML generation, all tools must use the "sakai.html.head" and "sakai.html.body.onload" request attributes as described below.

sakai.html.head
The tool should always inline the contents of the "sakai.html.head" request attribute in the HTML HEAD of the HTML documents it produces. This allows the portal to include JavaScript, CSS, and other fragments that it may need into the tool-generated HTML. For example, the Charon portal uses this mechanism to skin the tool.

sakai.html.body.onload
The tool should always inline the contents of the "sakai.html.body.onload" request attribute in the HTML BODY onload attribute of the HTML documents it produces. This allows the portal call JavaScript as needed. For example, the Charon portal uses this mechanism resize the tool's frame to fit its content.

For example, a JSF/JSP tool could include these attributes as follows:

<html>
    <head>
        <%= request.getAttribute("sakai.html.head") %>
        Tool's own head stuff here
    </head>
    <body onload="<%= request.getAttribute("sakai.html.body.onload") %>;foobar()">
        Tool main output here
    </body>
</html>

Feb. 4, 2007

I spoke with Antranig this morning:

AntranigBasman: I wouldn't advise it
AntranigBasman: But if you really must, you could use the UIFreeAttributeDecorator
mjnsakai: Well, Sakai tools require it.
AntranigBasman: I know
mjnsakai: There is a snippet of JavaScript that is required.
AntranigBasman: But the correct onLoad is already entered by RSF
mjnsakai: It isn't working for me.
mjnsakai: The tool isn't being sized correctly.
AntranigBasman: To what extent?
mjnsakai: I do see something in the onBody param, though.
mjnsakai: How come it isn't working for me?
AntranigBasman: You may have forgotten to put in the correct head matter
AntranigBasman: That references headscripts.js
mjnsakai: ah
AntranigBasman: RSF will also do this "semi-automatically" as well, but you do need to "hint" to it where to put it
AntranigBasman: Since you may want to choose to put some of your own head matter before, and after
mjnsakai: so how to I hint this?
AntranigBasman: You need the attribute rsf:id="scr=portal-matter" on some "placeholder" tag you have in <head> which is in the right place
mjnsakai: I've got the CCS links in.
AntranigBasman: Let me find an example...
mjnsakai: Maybe just <link rsf:id="scr=portal-matter">?
AntranigBasman: Well yeah
AntranigBasman: It is a little hard to get previewability for these definitions
AntranigBasman: Although it is possible...
AntranigBasman: https://source.sakaiproject.org/contrib/evaluation/trunk/tool/src/webapp/content/templates/template_modify.html
AntranigBasman: This is a current sample
AntranigBasman: I mean, you don't even need to have the correct name, or number for them
AntranigBasman: But it seems "reasonable" to put in 3 things, of the same types you know will be there (tongue)
mjnsakai: sweet. I can see it from the template_modify.html file.
AntranigBasman: But in theory this would work for other portals as well
AntranigBasman: Which might have entirely different requirements
AntranigBasman: In 0.7 we have achieved the "markup Nirvana" of having the correct Sakai-specific material inserted into the templates, without any Sakai-specific RSF tags required

The lines that need to be present in the header are:

    <link href="/library/skin/tool_base.css" rsf:id="scr=portal-matter" type="text/css" rel="stylesheet" media="all"/>
    <link href="/library/skin/default/tool.css" rsf:id="scr=portal-matter" type="text/css" rel="stylesheet" media="all"/>
    <script type="text/javascript" rsf:id="scr=portal-matter" language="JavaScript" src="/library/js/headscripts.js"></script>

Note the use of rsf:id="scr=portal-matter".
Added these lines to main.html and it works correctly now. Problem solved! Thanks to Antranig.

Added support to pass a collection id by creating AddCollectionViewParameters with a single parameter called "id". This defaults to none, so we known when no collection is being viewed. By making the collection names be links with this parameter, we should be able to view thumbnails.

Seems to be working correctly, though the id of the collection is not quite what I expected:

<a  href="http://localhost:8080/portal/tool/c79b04a3-acbe-4d0c-80b6-660ea38253cb/faces/main?id=/group/38414906-cfcb-485f-8047-99779b1d62b2/Galleries/Irish 
    Ruins/&amp;panel=Main" 
    id="collection-row:::collection-link">

The next step is to put the table wrapper around the navigation panel, and add a place-holder element where the thumbnails will be displayed.
Added code. Place-holder is working. Collection folders now serve as navigation links. I'm going to add a visual indicator that collection is selected using the open folder icon.

To do this, I need to conditionalize the image tag. Moving the IMG tag inside the SPAN doesn't work. It causes the icon to go away.
It doesn't look like there is a UIComponent for images. I may have to make one (if I can't talk Antranig into it). Looking at UILink, this doesn't look too hard.
The one thing that seems to be missing is how to identify the name of the parameter. Everything else is there. How does RSF know to render a UIImage compoment (once I create it) with a parameters of "src="?

It turns out there is no need for this. Once again, Antranig comes through:

mjnsakai: .Is there a component for <img> ?
AntranigBasman: Yes
AntranigBasman: UILink will peer with anything with a URL on it, in HTML
AntranigBasman: Including <a>, <img>, <iframe>, <script> etc.

Let's give it a try. Works as advertised. Now I can do a conditional to put the right icon in place.
Here's a snapshot showing the Irish Ruins collection selected:

The code to add thumbnails went fairly smooth. As I suspected, I needed to next two BranchContainers, one to hold the table row, the other to hold the table column. Handling left over images at the bottom of the table was a bit tricky, but worked once I got the math working (modulo arithmetic is so much fun). Here are two versions of the Gallery Tool showing thumbnail images for a selected image collection:

The view above shows images with scaling fixed at 100 x 100 pixels.

By contrast, the above image shows images with automatic scaling, depending on the browser window width.

The next step is to create the sequencing view, add links to it from the thumbnails.

Feb. 5, 2007

Created SequenceProducer class. Created AddImageViewParameters class. Added code to MainProducer to add a link to thumbnail image. Sequencer view just displays the id of the current image.

There was a problem when I created AddImageViewParameters. I left the id field as before, but changed the name of the parameter to "image". These two things have to agree. Once I changed the class parameter to match the CGI parameter name, all worked.

Updated the sequencing view wireframe and posted to Gallery Tool Design. Merged HTML into sequence.html. Enabled the image, name, and description.
Still to be done: breadcrumbs, return to main, nth of total, etc.

Feb. 6, 2007

Moved text of thumbs and slideshow links to Messages.properites. Removed resource id display.
Breadcrumbs now working.

Feb. 17, 2007

Created Gallery To Do to keep track of what needs to be done.
Attempted to implement the help/start page. This will be structured as conditionalized content on the gallery view page. The basic structure works fine: if there are no collections present, then the help page is displayed, other wise, the list of collections is shown.

Problems constructing the help/start text. Can't figure out how to style the section headers. There is a style for this, "h3.textPanelHeader", but it doesn't have a background color. My knowledge of CSS is fairly limited. I sent a message to the designers for help. Meanwhile, I'll just render it has an H3 header. The help/start text uses italics for emphasis. Need to get these tags to come through from the Message bundle. Currently, the tags are escaped and don't render correctly.

Antranig recommends using either UIVerbatim or injecting the MessageLocator and using it's methods. If I go with UIVerbatim, however, I need to upgrade to release M3.

Feb. 18, 2007

Added components for collection title, play slide show, and sort order in the thumbnails view.
Added another parameter to AddImageViewParameters to specify auto-sequencing.
Got "View slide show" link working in that it starts at slide one with auto set to true. Work is still needed to actually auto-sequence.
Added an init() method to MainProducer to initialize autoScale and galleryRoot from tool configuration parameters.

Move the root gallery Id and Name to the Message bundle. MessageLocator is then injected into GalleryServiceIpml. This all works, however, when it comes time to detect that the Gallery Tool needs to create a root folder, the folder is created (presumably with the right id), but I can't get the display name to appear in the Resoources tool. Current code is:

//  If we didn't find one, then we need to make one.
ContentCollectionEdit newGallery = null;
if (this.gallery == null) {
	try {
		newGallery = ContentHostingService.addCollection(rootId+"/"+galleryId);
	}
	catch (IdUsedException ex1) {ex1.printStackTrace(); return;}
	catch (IdInvalidException ex2)  {ex2.printStackTrace(); return;}
	catch (PermissionException ex3)  {ex3.printStackTrace(); return;}
	catch (InconsistentException ex4)  {ex4.printStackTrace(); return;}

	ResourcePropertiesEdit newProps = newGallery.getPropertiesEdit();
	newProps.addProperty(ResourceProperties.PROP_DISPLAY_NAME, messageLocator.getMessage("gt_gallery_name"));

	ContentHostingService.commitCollection (newGallery);
	this.gallery = newGallery;

	System.out.println ("\n***** GalleryService.initGallery - new gallery created.");
}

Changed the id back to "Galleries" from "Gallery_Tool_Collections" so that I can keep on working. I'll send mail to Jim Eng to get help on Content Hosting.

Feb. 19, 2007

Got a note from Jim Eng last night. He says the sequence is fine, but I should check messageLocator.getMessage("gt_gallery_name") to make sure it actually gets a string.
Spend time trying to debug the Gallery Tool Collections folder name, with no success.
Turned to image sequencing.
Added UIForm and UICommands for each of the four sequencing buttons.
I'm trying to get them to invoke an action handler and intialize a seqAction command variable.
Tried to get the value of the submit button to be put into a form parameter. You can do this with regular CGI, but RSF doesn't seem to support it. It really wants to use action handlers.
Antranig said that action handlers should be in their own beans.
I will create a SequenceBean.

Feb. 20, 2007

Creating a SequenceBean for the action handlers is the first step. The handlers are now being called now that I removed the method="#" from the FORM tag. This forces RSF to assume it is a GET form, whereas we want it to be treated as a POST to be able to differientate between the different submits. The SequenceBean has methods that set a seqAction command variable. However, when SequenceProducer calls adjustViewParameters(), the command is reset to it's default case.

Antranig tells me that there are, in fact, two requests happening here: the iniial form submit and the view render. This causes all beans in request scope to be re-instantiated, which explains the behavior I'm seeing. By moving the SequenceBean (and the GalleryServices, since it depends on it) into the applicationContext, the sequence logic works, though I had to fix a bug which cuased it to run off the end of the sequence.

Antranig says that this is not right. The SequenceBean should, in fact, be in session scope so that it's state will be preserved across requests. This makes sense because the UI does have user-specfic state. The question is how to make this bean have session scope. Antranig refers me to: http://bugs.sakaiproject.org/confluence/display/BOOT/RSF+and+Spring+Contexts in the Programmer's Cafe.

Feb. 22, 2007

A session scope bean in RSF requires an anchoring bean that is in application scope. Since the session bean is really just a request scope bean, it needs something in the application scope to hold it. In the Gallery Tool, we have the SequenceBean, which holds state from the sequencing buttons on the Sequence page. If this bean is declared in the requestContext file, it will come and go during the request. Since the request is multi-phase, the bean loses it's sate before it can be accessed by the producer (SequenceProducer). The trick is to create a special scope in the applicationContext to anchor the bean into a session scope. Thus:

requestContext:

  <bean id="sequenceBean" class="org.sakaiproject.gallery.tool.SequenceBean" singleton="true">
  	<property name="galleryService" ref="galleryservice" />
  </bean>

Note that the GalleryService must remain in application scope, since it must have a longer scope than SequenceBean if it is to be injected into it. Services are typically held in application scope anyways,according to Antranig. Now we define the anchoring scope that will hold SequenceBean in session scope:

applicationContext:

  <bean id="galleryservice" class="org.sakaiproject.gallery.impl.GalleryServiceImpl">
    	<property name="messageLocator" ref="messageLocator" />
  </bean>

<bean id="myBeanScope" parent="beanScopeParent">
	<property name="copyPreservingBeans" value="sequenceBean" />
	<property name="exclusive" value="true" />
</bean>

This defines a session scope bean called myBeanScope, which is a sibling of beanScopeParent (presumably an RSF defined bean - this should be verified). The value ofthe copyPreservingBeans is a comma separated list of beans that should be preserved beyond the request, ie. in a session. it isn't clear at this point how thiis is tide to a particular kide of session (tool, user, etc.).

IN a sense, this is a way to pull a bean partially out of request scope, mid-way towards application scope.

I suspect that SequenceBeam still needs to be inclued in requestAccesibleBean so that it can be referenced.

Changes made to gallery tool. Tested and works. Sequence is now taking place in session scope (in theory, any way to verify this?).

Fixed "Return to thumbs view" link. Remembers which collection is selected.

Noted an interesting comment on the "tool state" that raged on the sakai-dev list recently. If you are on the image display page (say), click on the Resources tool, and then clock on the Gallery tool, you lose all gallery tool state, ie, it returns to gallery selection view. Thinking about it, this is what you'd expect, though I suspect the guys at UCB are not going to like it.

Feb. 23, 2007

Demonstrated Gallery Tool for Mara, Ray, Daphne, and Samus at UC Berkeley. Samus mentioned additonal changes, but couldn't find them in email. They may be at home.

Feb. 24, 2007

Started thinking about auto-sequencing. There is nice Java Timer example that could be used to support auto-sequencing. I note, however, that to start the time when the page is loaded, I'm going to have to include it in the onload parameter in the BODY tag. This is already being stuffed by RSF. I'll need to consult with Antranig about this.

Had problems with LodgeNet terminating my save request in Confluence. Seems it uses up too much bandwidth, so they throttle me back to 56kb. Operator said that the connection isn't terminated, but text is lost, so that's hard to believe. I'm going to have to keep the notes here and upload them later.

Spoke with Antranig about adding Javascript calls to onload. He recommends against it, but putting in a JS call just after the BODY tag will accomplish the same thing. There is a mechanism in RSF to RSF-tagged elements, but I don't it's needed here. Rather, we can do something like this:

<body>
    <script>
        startTimer(10);
    </script>
 ...
<.body>

Add the following code to timer.js:

//  This code borrowed from Paul McFedries
//  http://www.mcfedries.com/JavaScript/timer.asp
var secs
var timerID = null
var timerRunning = false
var delay = 1000

function InitializeTimer()
{
    // Set the length of the timer, in seconds
    secs = 5
    StopTheClock()
    StartTheTimer()
}

function StopTheClock()
{
    if(timerRunning)
        clearTimeout(timerID)
    timerRunning = false
}

function StartTheTimer()
{
    if (secs==0)
    {
        StopTheClock()
        // Here's where you put something useful that's
        // supposed to happen after the allotted time.
        // For example, you could display a message:
        alert("*** TIMER ALERT ***"")
    }
    else
    {
        self.status = secs
        secs = secs - 1
        timerRunning = true
        timerID = self.setTimeout("StartTheTimer()", delay)
    }
}

Added a script tag in the header to load this code. First step is to make sure it gets into the HTML conditionally based on the auto parameter.
Code is conditionally added as:

<script  type="text/javascript" src="http://localhost:8080/gallery/content/templates/timer.js" language="JavaScript" id="timer-script"></script>

It's rather naive to put all my resources in the template directory, but I'd rather spend the time getting functionality to work than figuring out the vagarities of including content in other spaces.

Added conditionalized entry of a script tag just after the body to invoke the timer (InitializeTimer()). Timer successful starts and results in an alert box 5 seconds later. Clicked on Start slide show and immediately clicked on "Next" button. Timer still triggered and alert comes up. I need to fix the sequence buttons so that they set auto to off. Code was just picking up the current value of autoSeq and using it to create the view parameters. Checked it to hard-set it to OFF. Eventually, I will have conditionalize the "Start slide show" on the sequence page to "Stop slide show" and have it stop on the current slide.

Worked. Clicking on any of the sequencing buttons will take application out of auto-sequence mode.
I may as well add the start / stop link on the sequencing page at this point.
Start and stop link is working in Sequence view. The user has the following options to stop a slide show in progress:

  1. Click on the "Stop Slide Show" link
  2. Click on "Goto First" button
  3. Click on "Goto Previous" button
  4. Click on "Goto Next" button
  5. Click on "Goto Last" button
  6. Click on "Return to thumbnails" link

Fixed image scaling on image view page to show full screen.
Fixed sequencing buttons to show symbolic names rather than words. It can still be changed in the Messages bundle, if desired.

Antranig also pointed me to http://www.quirksmode.org/js/iframe.html that discusses changing the URL location of an HTML document in an iFrame (etc). He mentioned that the new components page in RsfWiki talks about Javascript, etc.

It looks like we can get at the URL for a link using the following code snippet:

    ViewParameters seqParams = new SimpleViewParameters(SequenceProducer.VIEW_ID);
    String SeqenceUrl = viewStateHandler.getFullURL(seqParams);

and can be used with AddImageViewParameters instead of SimpleViewParameters as well.

Just about ready to try auto sequencing. Taking it one step at a time, I will try to advance to a fixed url (http://www.nolaria.com) before attempting to put in an RSF URL. Successfully advanced to external URL. One more test before putting in RSF link. I will set the URL in the body of the sequence view.

Some trouble with including quotes in java strings. If I use HTML codes, the javascript to set the URL is rendered as:

seqUrl=&amp;quot;http://www.sakaiproject.org&amp;quot;; InitializeTimer()

I might have to use UIVerbatim here, else figure out what the escape code is for quotations in Java strings.
Yeah, even escaping the quotes in the strings resulted in:

timer-start">seqUrl=&quot;http://www.sakaiproject.org&quot;; InitializeTimer()

Using UIVerbatim did the trick. Transitioned to "www.sakaiproject.org" correctly.

The trick to stopping auto-sequence at the of the sequence is to detect when the next slide is the last slide and setting auto to off for that transition.

See these utilities for Javascript support in RSF.

AntranigBasman: HTMLUtil.emitJavascriptCall
AntranigBasman: There is also emitJavascriptArray
AntranigBasman: and emitJavascriptVar - you shouln't need anything else if you are using RSJCIS in the recommended way

Have a look at these utilties and see if they can be made to work rather than the current hack.

All that remains is to compute the URL to sequence to and injected it into the Javascript.
It looks like I have to inject the ViewStateHandler provided by RSF into my SequenceProducer in order to resolve URLs from view states.
I had to fix and off by one effort on detecting the last slide, but auto-sequencing now works correctly. It might be a good idea to parameterize the timing of the slides. Five seconds seems like a good amount of time, but not if you are really going to look at the images. Also, no matter what you do, scaling doesn't seem to work right. It might be worth experimenting to scaling to the height instead of the width. That might force it onto the screen by default.

Feb. 28, 2007

Debugging Gallery Collection creationg display name.

Added some println's to show the display name before and after the commit. I'm not relying on the local value, either. I'm fetching the ResourceProperties object fresh each time. In both cases, the display name seems to be presesnt in the ResourceProperties.
I am beginning to suspect that either the refresh hasn't actually happened, or that the Resources tool uses a different method to get the display name than I'm using to set it. No, I don't think that the commit is actually happening.

Interestingly, the Content Hosting Service has a variation of addCollection() that takes a ResourceProperties object as an argument. If there was a way to create the properties before, that might work better. However, I can't see a way to create an empty properties object.

Tried doing two commits. That didn't work. Interestingly, I did get a warning from CHS:

WARN: commitCollection(): closed ContentCollectionEdit (2007-02-28 17:46:14,437
http-8080-Processor25_org.sakaiproject.content.impl.BaseContentService)

Two commits won't work, obviously, but why are the properties of a new collection not getting persisted?

The implementation of ResourceProperties.addProperty() is in the utils module of Entity. It merely adds the name/value pair to an interal HashTable object called m_props.

There is nothing in this implementation that flags a ResourceProperties object as being modified. So how does CHS know that the properties have been modified? My guess would be that it assumes that properties are always written out on a commit(), but maybe that is not the case.

I have verified that if I could get at a ResourceProperties object, that it would be auto-committed in the addCollection().
I could cheat. There doesn't seem to be a factory to create ResourceProperty objects (why not?). However, the BaseResourceProperties class is in entity utils, which seems to imply that it's ok to use it's constructor.

If a bug needs to be submitted, I can extract the code out of the backup. It sure looks like a bug.

Started the code changes to create the ResourceProperties object before the addCollection(). Doesn't compile. Fix and test.

Mar. 2, 2007

There were some weird problems with the code the prevented it from compiling, but I got over them. Also, trying to access a BaseResourceProperties object from the entity utils proved to be difficult. It's not clear that it's deployed in the normal manner. Regardless, the CHS has a method called newResourceProperties() that returns a ResourcePropertiesEdit object. Set the code to call that, and set the display name property. Fails the same way as before: collection is created with no display name. Obviously I am not creating the name of a resource the same way that the Resource Tool is. This is the only explanation I can come up with.

I moved my new CHS analysis tool over to the Gallery Test site and used it to have a look at the resources saved in the site. Interestingly, the empty collection CONTAINS a collection called "Gallery Tool Collections". Looks like the bug is that my path name for creating the collection is wrong. It probably has an extra slash in it. Nice to know that the effort I spent creating this tool paid off. Verified fixed. Moved image collections into "Gallery Tool Collections" and deleted "Galleries".

Parameterized auto-sequence delay. Parameter is defined in the tool definition file as "gallery.slide.time".

Mar. 6, 2007

Time for the final push on phase I of the Gallery Tool. Sorting is the last major piece of functionality, followed by some small content adjustment and some code clean-up.

Added a sort parameter to AddCollectionViewParameters.
It looks like I have to use the UISelect compoment for the sort radio buttons. Antranig confirms this. This should be wirtten up in the training notes as well.
Selection isn't completely obvious from looking at the RSF component code. It looks like UISelect is a container for UISelectChoice and UISelectLabel components. While it will delay things, it might be best to code up a few examples of these selection components and experiment with them.

I found an example of radio buttons in rsf/RSFSamples/RSFComponents/.../ControlsProducer.java:

	// Radio Buttons
	String [] radioValues = new String[] {"pop","soda","coke"};
	String [] radioLabels = new String[] {"Pop","Soda","Coke"};
	UISelect radios = UISelect.make(simpleform, "carbonationradio", radioValues, 
			"#{simpleformbean.carbonation}", "Carbonation");
	radios.optionnames = UIOutputMany.make(radioLabels);
		
	String selectID = radios.getFullID();
	UISelectChoice.make(simpleform, "popradio", selectID, 0);
	UISelectChoice.make(simpleform, "sodaradio", selectID, 1);
	UISelectChoice.make(simpleform, "cokeradio", selectID, 2);

This code corresponds to a template that looks like this:

        <span rsf:id="carbonationradio"/>
        <label for="popradio">Pop</label>
        <input 	type="radio" rsf:id="popradio" />
        <label for="sodaradio">Soda</label>
        <input 	type="radio" rsf:id="sodaradio" />
        <label for="cokeradio">Coke</label>
        <input 	type="radio" rsf:id="cokeradio" />

Now we see where the terms in the RSF code comes from. Antranig is assuming that radio controls will make use of the LABEL tag, though there are other ways to represent this in a HTML form.

So step one should be to fix up the HTML in the gallery page view to use LABEL tags:

<form method="#" rsf:id="sort-form">
	<input rsf:id="sort-coll-id" type="hidden" />
	<span rsf:id="sort-order" style="font-weight: bold;" />Sort order instruction goes here.</span>
	<input 	type="radio" rsf:id="instr-radio" />
	<label for="instr-radio">Instructor label here.</label>
	<input 	type="radio" rsf:id="alpha-radio" />
	<label for="alpha-radio">Alphabetic label here.</label>
</form>

Note that I have inverted the order of the INPUT and LABEL tags to reflect the UI design specified by Seamus at Berkeley.
Note also that rsf:id on the INPUT is used in the FOR parameter of the LABEL tag. These must agree since that is how RSF links one to the other.

Producer code is written as:

	UIForm sortForm = UIForm.make(tofill, "sort-form", new AddCollectionViewParameters (MainProducer.VIEW_ID, thumbCollectionId,
		AddCollectionViewParameters.SORT_INSTRUCTOR));

	String [] sortValues = new String[] {AddCollectionViewParameters.SORT_INSTRUCTOR, AddCollectionViewParameters.SORT_ALPHA};
	String [] sortLabels = new String[] {this.messageLocator.getMessage("gt_instr_order"), this.messageLocator.getMessage("gt_instr_order")};

	UISelect radios = UISelect.make (sortForm, "sort-order", sortValues, sortLabels, AddCollectionViewParameters.SORT_INSTRUCTOR, true);
	radios.optionnames = UIOutputMany.make(sortLabels);

	String selectId = radios.getFullID();

	UIInput.make(sortForm, "sort-coll-id", thumbCollectionId);
	UISelectChoice.make(sortForm, "instr-button", selectId, 0);
	UISelectChoice.make(sortForm, "alpha-button", selectId, 1);

Antranig indicated that I do not have to explicitly include a hidden input to retain the collection id. RSF will fossilize it for me and carry it through to the View Parameter object. I removed the hidden field for it.
He also mentioned that I can decorate the UISelectChoice objects with onClick() to make them auto-submit.

Labels are not being rendered. Antranig says I need to include UISelectChoice object.
He recommended an different example, UploadDemoProducer

Ok, the sort controls are rendering correctly now. I had to add a prompt span, which I didn't think I needed, but other exmaples show it is.

The current HTML is:

<form method="#" rsf:id="sort-form">
	<span rsf:id="sort-order" />
	<span rsf:id="sort-instruction" style="font-weight: bold;" >Sort order instruction goes here.</span>
	<input 	type="radio" rsf:id="instr-radio" />
	<label rsf:id="instr-label">Instructor label here.</label>
	<input 	type="radio" rsf:id="alpha-radio" />
	<label rsf:id="alpha-label">Alphabetic label here.</label>
</form>

The current producer code is:

//	Sort form
UIForm sortForm = UIForm.make(tofill, "sort-form", new AddCollectionViewParameters (MainProducer.VIEW_ID, thumbCollectionId,
	AddCollectionViewParameters.SORT_INSTRUCTOR));

String [] sortValues = new String[] {AddCollectionViewParameters.SORT_INSTRUCTOR, AddCollectionViewParameters.SORT_ALPHA};
String [] sortLabels = new String[] {this.messageLocator.getMessage("gt_instr_order"), this.messageLocator.getMessage("gt_alpha_order")};

UISelect radios = UISelect.make (sortForm, "sort-order", sortValues, sortLabels, sortMode, true);
//radios.optionnames = UIOutputMany.make(sortLabels);

String selectId = radios.getFullID();
UIOutput.make(sortForm, "sort-instruction", messageLocator.getMessage("gt_sort_order"));

UISelectChoice.make(sortForm, "instr-radio", selectId, 0);
UISelectLabel.make(sortForm, "instr-label", selectId, 0);
UISelectChoice.make(sortForm, "alpha-radio", selectId, 1);
UISelectLabel.make(sortForm, "alpha-label", selectId, 1);

I need to add the onClick decoration now.
Added to HTML as:

<form method="#" rsf:id="sort-form">
	<span rsf:id="sort-order" />
	<span rsf:id="sort-instruction" style="font-weight: bold;" >Sort order instruction goes here.</span>
	<input 	type="radio" rsf:id="instr-radio" onClick="document.forms[0].submit()"/>
	<label rsf:id="instr-label">Instructor label here.</label>
	<input 	type="radio" rsf:id="alpha-radio" onClick="document.forms[0].submit()"/>
	<label rsf:id="alpha-label">Alphabetic label here.</label>
</form>

Just have to add the actual sorting and this will be done. It occurred to me, however, that UBC might want to preseve the sort mode into the sequencing - both automatic and manual. OTOH, this might be confusing, so we'll just leave it as instructor sort mode for now and fix it later if needed.

Created an AlphabeticImageComparator that compares two images based on their display names. Added sort mode to ImageCollection. Sort selection buttons now work correctly. Sort mode is NOT carried over to sequencing. Sort mode resets to default when returning from image view to thumbs view.

Mar. 7, 2007

After tinkering with it for hours, I got the grey section bands to come up in the gallery tool. The HTML looks like this:

<div style="background-color: #DEDEDE; color=#333333; padding: .3em; 
    font-size: 13pt; margin: auto 0 auto 0;" 
    rsf:id="help-coll-title">
        Add to a collection title goes here.
</div>

Fixed up the text in the help page. It all seems to look right.
Added click prompt on thumbs side if no collection is selected.

Pretty much all that's left is filtering on image type. Some research indicates that we should support the following kinds of image resources:

MIME Type

File Ext.

image/bmp

.bm

image/bmp

.bmp

image/gif

.gif

image/jpeg

.jfif

image/jpeg

.jfif-tbnl

image/jpeg

.jpe

image/jpeg

.jpeg

image/jpeg

.jpg

image/pict

.pic

image/pict

.pict

image/png

.png

image/png

.x-png

image/tiff

.tif

image/tiff

.tiff

Since the content hosting service will give me back resource types as MIME types, I really only have to worry about: image/bmp, image/gif, image/jpeg, image/pict, image/png, and image/tiff. Of these, I'm not sure of the support for pict and tiff, but it shouldn't matter if the Gallery Tool is more open than CHS.

At first I thought to inject the list of image types via Spring, but that would mean some configuration is done in the tool setup and others in the spring file. So I moved it to the tool registration file. The Gallery Service already has a dependency on the ActiveToolManager, so adding another parameter won't hurt it. Tested it in two ways. The Irish collection still shows fine. Added a test file to the Frank Lloyd Write collection and made sure it doesn't show.

Reset auto sizing in the tool registration file.
Changed the category names in the tool regsitration file to be:

<category name="course" />
<category name="project" />

This should allow the gallery tool to be picked from worksite setup.

Apr. 4, 2007

Gallery Tool review. A number of issues were filed into Jira at Gallery Jira Issues .

Apr. 4, 2007

Downloaded and built version 009 of Sakai 2.4.0. Compliled, deployed, and starts up without error. I haven't added the Gallery module yet, since I know it will fail.

GAL-16 - Getting issue details... STATUS indicates that the tool doesn't build under 2.4.0. Since bSpace is moving to 2.4, this is a requirement. Most of this work will be in upgrading the tool to RSF 0.7.1 and making some adjustments to maven to make it build correctly. I don't anticipate that changes to RSF will case problems, but that remains to be seen.

The distribution doesn't seem to include RSF (no real surprise, but I was hoping). Had to download sakai-rsf manually from SVN. Built without error. Moved gallery directory into this neivonrment. Failed to build (again, no surprise). It's failing on:

Attempting to download rsfutil-0.7.1.jar.
WARNING: Failed to download rsfutil-0.7.1.jar.
Attempting to download sakairsf-0.7.1-sakai_dev.jar.
WARNING: Failed to download sakairsf-0.7.1-sakai_dev.jar.

The sakairsf module seems to be be replaced by "sakai-contextlocator-api" with a listener to provide access to the Sakai context. I recall Antranig talking about this in an earlier conversation, but I'm not sure what impact it has on me. The "SakaiRSF" page in RSF Wiki doesn't seem to talk about this at all.

Looks like the right version of rsfutil should be 0.7.1M6.
Yes, that resolved that issue. Now I'm down to how this Sakai Context Loader thing works.
I tried commenting out the reference to sakairsf (since I'm not using any of the standard components). It builds successfully.
However, errors are thrown at startup time. Let's have a look at catalina.out:

WARN: Servlet 2.4 or below detected. Unable to find getContextPath on ServletContext.

Could cause a problem, but this seems to be generated by PortletContextManager, and not the Sakai framework. I think we can ignore that.
The first gallery exception is:

ERROR: Context initialization failed (2007-04-05 14:25:47,093 main_org.springframework.web.context.ContextLoader)
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource conf/sakai-applicationContext.xml; nested exception is java.io.FileNotFoundException: class path resource conf/sakai-applicationContext.xml cannot be opened because it does not exist
java.io.FileNotFoundException: class path resource conf/sakai-applicationContext.xml cannot be opened because it does not exist

This is very likely what changed. There is a reference to the sakai application context. There is now a Sakai Context Loader. It might be as simple as invoking the loader listener that is provided in sakai-rsf, since it just adds a bean. Maybe I can find updated verisons of the examples in the RSF subversion tree.
It doesn't look like the examples have been updated. I find no reference to LocatorServletContextListener, which is what's included in sakai-contextlocator-util.

I'm gonna have to talk to Antranig about this.
Antranig provided the correct project.xml code. There have been minor changes to the sakai-rsf compoment.
Fixed, checked in.

Apr. 9, 2007

Started work on GAL-2 - Getting issue details... STATUS which states that only one person can use the Gallery tool at one. This is likely related to static variables, perhaps the SequenceBean. Antranig recommended removing this, so I'm looking into doing just that.

Atranig's recommendations were:

  1. Eliminate SequenceBean
  2. Remove references to MessageLocator
  3. Improve exception handling and add logging. Universal Runtime Exception (URE)
  4. Make sure that running off ends of sequence is fully handled.
  5. Name space all Javascript. Simplify start of JS timer. HTMLUtil.emitJavascriptCall()
UIVerbatim.make(tofill, "timer-start", "secs="+this.delay+"; seqUrl=\""+nextUrl+"\"; InitializeTimer()");

try {
   .... old-style checked-exception API
   }
catch (Exception e) {
   throw UniversalRuntimeException.accumulate(e, "What I learned in this catch block" );
}

After thrashing around for a while, I got it to work by changing the UICommands to:

UICommand.make(form, "seq-submit-last", this.messageLocator.getMessage("gt_seq_last"), null);

and adding an onClick javascript command in the template for each button:

<input type="submit" value="|<" rsf:id="seq-submit-first" onClick="document.forms0.seq.value='1'" />

In theory, this should allow me to convert the sequence form to a GET, rather than a POST, but I'm not worried so much about that. I could also move the javascript into the producer code as decorations on the submit elemements. That would keep the state definitions in the code and out of the template, though it doesn't seem very likely that more than four states for sequencing is ever needed.

Files changed to fix GAL-2:

  • SequenceProducer.java
  • applicationContext.xml
  • requestContext.xml
  • sequence.html
  • sequenceBean.java (deleted)

Having made these changes, does it really fix the bug? It's difficult for me to test this here, but it is the obvious source of sequencing problems.
Checked all java files for static variables and found only static final ones (constants).
Looking at the GalleryServiceImpl, I note that in the init() method sets the gallery variable in the service. Since the service is in application context, this initialization is only done once, and will be retained for ever. This even applies to other users coming in to use a defferent gallery in a different site. Yikes! This is very bad. The simple fix is to move the gallery service bean into context scope, which means that it would be initialized on every request. That introduces some over head, but not a lot, I think.

Apr. 10, 2007

Time for the image sizing problem, GAL-6 - Getting issue details... STATUS . Seamus has created a mockup of thumbnail HTML that allows thumbnails to wrap on a line automatically based on the space availabale. It's based on how text flows in a browser. The basic unit (each thumnail) is this:

 

<div class="float">
<img src="images/image01.gif"
alt="image 1" />
<div class="caption">Yellow Blue </div>

</div>
{code:

Frankly, this is far simpler than the table layout, though personally I like the table layout.
Added a new CCS file called images.css provided by Seamus.

Files changed to fix GAL-6:

  • main.html
  • MainProducer.java
  • images.css

Next up is showing instructions when a site has the Gallery Tool, but no Resources tool, GAL-4 - Getting issue details... STATUS .
Confirmed the problem by created the "No Resources" site. Selecting the Gallery Tool in this site gives:

Fatal internal error handling request:
Target exception of class java.lang.NullPointerException
Successive lines until stack trace show causes progressing to exception site:

java.lang.NullPointerException
at org.sakaiproject.gallery.impl.GalleryServiceImpl.getCollections(GalleryServiceImpl.java:141)
at org.sakaiproject.gallery.tool.MainProducer.fillComponents(MainProducer.java:144)
at uk.org.ponder.rsf.view.ViewCollector.fillComponents(ViewCollector.java:52)

Made initGallery() public in GalleryService. Added a testable flag to see if it is intialized. Fixed implementations of service to check it.
Added a new message in Message Bundle to hold instructions provided by Seamus. It looks a bit ugly, but whatever.

Files changed to fix GAL-4:

  • main.html
  • MainProducer.java
  • GalleryService.java
  • GalleryServiceImpl.java
  • Messages.properties

Close look at the sequencing page showed the breadcrumbs and image names under image to be wrong. Simple fix in SequenceProducer. GAL-6 - Getting issue details... STATUS

Files changed to fix GAL-6:

  • SequenceProducer.java

Several minor bugs fixed.