The GSoC 2009 XWiki blog

The GSoC 2009 XWiki blog

This blog aggregates all the other blogs, and holds important announcements

Oct 29 2009

Drag&Drop iGoogle like Dashboard

I've been playing around with Smartclient to create an iGoogle like Dashboard with drag&drop windows for the Apps. You can play with it here:

App Dashboard

Aug 24 2009

Files listing

Changes on xwiki-web-standard module (patch)

These changes comprise new velocity files, Shindig JS files, Shindig container configurations, modifications to module's web.xml and pom.xml files.

in standard/src/main/webapps/templates:

Additional Velocity files:

  • addapplication.vm - installs an application from the directory for a user; the result is a document with an OpenSocialApplication.ApplicationClass attached to it, in the Space OpenSocialApplication; also specific rights are set for the document: all to self, some to admin, only view to others
  • getuserprefs.vm - returns a JSON with all the OpenSocial User Preferences set/saved by a specific gadget/application; the UserPrefs are key-value pairs, and are stored as OpenSocial.UserPrefClass objects attached to installed application pages
  • saveuserprefs.vm - saves new User Prefs for a application and user
  • addfriend.vm - adds a friend for a user; friends are XWiki.FriendClass objects attached to a user's profile page. XWiki.FriendClass objects have a property called friendName wich keeps the document full name of the user friend
  • getuserfriends.vm - returns the friends of a user
  • deletefriend.vm - deletes a friend

in standard/src/main/webapps/resources/xwiki/opensocial:

Added javascript and css files necessary for the Shindig client container:

  • gadgets.js
  • rpc.js
  • util.js
  • json.js
  • gadgets.css

in standard/src/main/webapps/WEB-INF:

Modified web.xml to include all shindig servlet mappings and necessary Guice modules:

  • Shindig Guice modules:
<!-- Shidig Guice modules -->
  <context-param>
    <param-name>guice-modules</param-name>
    <param-value>
      org.apache.shindig.common.PropertiesModule:
      org.apache.shindig.gadgets.DefaultGuiceModule:
      org.apache.shindig.gadgets.oauth.OAuthModule:
      org.apache.shindig.common.cache.ehcache.EhCacheModule:
      org.xwiki.opensocial.social.XWSocialModule
    </param-value>
  </context-param>

  • Shindig filters:
<!-- Shindig filters -->
  <filter>
    <filter-name>authFilter</filter-name>
    <filter-class>org.apache.shindig.auth.AuthenticationServletFilter</filter-class>
  </filter>

  • Shindig filter mappings:
<!-- Shindig filter mappings -->
  <filter-mapping>
    <filter-name>authFilter</filter-name>
    <url-pattern>/social/*</url-pattern>
  </filter-mapping>

<filter-mapping> <filter-name>authFilter</filter-name> <url-pattern>/gadgets/ifr</url-pattern> </filter-mapping>

<filter-mapping> <filter-name>authFilter</filter-name> <url-pattern>/gadgets/makeRequest</url-pattern> </filter-mapping>

<filter-mapping> <filter-name>authFilter</filter-name> <url-pattern>/gadgets/api/rpc/*</url-pattern> </filter-mapping>

<filter-mapping> <filter-name>authFilter</filter-name> <url-pattern>/gadgets/api/rest/*</url-pattern> </filter-mapping>

  • Shindig Guice listener:
<!-- Shindig Guice listener -->
  <listener>
    <listener-class>org.apache.shindig.common.servlet.GuiceServletContextListener</listener-class>
  </listener>

  • Shindig Servlets:
<!-- Render a Gadget -->
  <servlet>
    <servlet-name>xml-to-html</servlet-name>
    <servlet-class>
      org.apache.shindig.gadgets.servlet.GadgetRenderingServlet
    </servlet-class>
  </servlet>

<!-- Proxy --> <servlet> <servlet-name>proxy</servlet-name> <servlet-class> org.apache.shindig.gadgets.servlet.ProxyServlet </servlet-class> </servlet>

<!-- makeRequest --> <servlet> <servlet-name>makeRequest</servlet-name> <servlet-class> org.apache.shindig.gadgets.servlet.MakeRequestServlet </servlet-class> </servlet>

<servlet> <servlet-name>concat</servlet-name> <servlet-class> org.apache.shindig.gadgets.servlet.ConcatProxyServlet </servlet-class> </servlet>

<!-- OAuth callback --> <servlet> <servlet-name>oauthCallback</servlet-name> <servlet-class> org.apache.shindig.gadgets.servlet.OAuthCallbackServlet </servlet-class> </servlet>

<!-- Metadata RPC --> <servlet> <servlet-name>metadata</servlet-name> <servlet-class> org.apache.shindig.gadgets.servlet.RpcServlet </servlet-class> </servlet>

<!-- javascript serving --> <servlet> <servlet-name>js</servlet-name> <servlet-class>org.apache.shindig.gadgets.servlet.JsServlet</servlet-class> </servlet>

<!-- Serve social REST api --> <servlet> <servlet-name>socialRestapiServlet</servlet-name> <servlet-class> org.apache.shindig.protocol.DataServiceServlet </servlet-class> <init-param> <param-name>handlers</param-name> <param-value>org.apache.shindig.social.handlers</param-value> </init-param> </servlet>

<!-- Serve social RPC api --> <servlet> <servlet-name>socialJsonRpcServlet</servlet-name> <servlet-class> org.xwiki.opensocial.social.XWikiShindigServlet </servlet-class> <init-param> <param-name>handlers</param-name> <param-value>org.apache.shindig.social.handlers</param-value> </init-param> </servlet>

<!-- Serve gadgets RPC api --> <servlet> <servlet-name>gadgetsJsonRpcServlet</servlet-name> <servlet-class> org.apache.shindig.protocol.JsonRpcServlet </servlet-class> <init-param> <param-name>handlers</param-name> <param-value>org.apache.shindig.gadgets.handlers</param-value> </init-param> </servlet>

<!-- Serve gadgets REST api --> <servlet> <servlet-name>gadgetsRestapiServlet</servlet-name> <servlet-class> org.apache.shindig.protocol.DataServiceServlet </servlet-class> <init-param> <param-name>handlers</param-name> <param-value>org.apache.shindig.gadgets.handlers</param-value> </init-param> </servlet>

  • Shindig Servlet mappings:
<!-- Shindig servlet mappings -->
  <servlet-mapping>
    <servlet-name>js</servlet-name>
    <url-pattern>/gadgets/js/*</url-pattern>
  </servlet-mapping>

<servlet-mapping> <servlet-name>proxy</servlet-name> <url-pattern>/gadgets/proxy/*</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>makeRequest</servlet-name> <url-pattern>/gadgets/makeRequest</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>gadgetsJsonRpcServlet</servlet-name> <url-pattern>/gadgets/api/rpc/*</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>gadgetsRestapiServlet</servlet-name> <url-pattern>/gadgets/api/rest/*</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>concat</servlet-name> <url-pattern>/gadgets/concat</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>oauthCallback</servlet-name> <url-pattern>/gadgets/oauthcallback</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>xml-to-html</servlet-name> <url-pattern>/gadgets/ifr</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>metadata</servlet-name> <url-pattern>/gadgets/metadata</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>socialRestapiServlet</servlet-name> <url-pattern>/social/rest/*</url-pattern> </servlet-mapping>

<servlet-mapping> <servlet-name>socialJsonRpcServlet</servlet-name> <url-pattern>/social/rpc/*</url-pattern> </servlet-mapping>

in standard/src/main/webapps/WEB-INF/classes:

Added container/default/container.js and shindig.properties - shindig container configurations files. I modified the base URLs for the services provided by Shindig, so they all contain /xwiki/.
For example, http://%host%/gadgets/api/rpc becomes http://%host%/xwiki/gadgets/api/rpc.
I placed the 2 files in the classpath, as they required modifications from the original files.

in standard/src/main/webapps/resources/icons/silk:

  • os_app.js - added an icon for the gadgets (used in css)

in standard:

Modified pom.xml, to include as a dependency xwiki-social-opensocial module

<!-- The OpenSocial module -->
    <dependency>
      <groupId>org.xwiki.platform</groupId>
      <artifactId>xwiki-social-opensocial</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>

XClasses and documents created (.XAR Application)

  • OpenSocial.AppDataClass - Application data created by applications for a specific user. Objects of this type are saved as attachments on installed application pages (pages containing objects of type OpenSocialApplication.ApplicationClass); App data is saved in the form of key-value pairs
  • OpenSocial.AppDataClassSheet - default content
  • OpenSocial.AppDataClassTemplate - default content
  • OpenSocial.Dashboard - Displays applications all installed applications for the logged in user in the profile/default view form; The page script includes shindig JS files, retrieves all apps of interest, adds them to the container, and renders them:
$xwiki.jsfx.use("js/xwiki/opensocial/json.js")
$xwiki.jsfx.use("js/xwiki/opensocial/rpc.js")
$xwiki.jsfx.use("js/xwiki/opensocial/cookies.js")
$xwiki.jsfx.use("js/xwiki/opensocial/util.js")
$xwiki.jsfx.use("js/xwiki/opensocial/gadgets.js")
$xwiki.ssfx.use("js/xwiki/opensocial/gadgets.css")
$xwiki.jsx.use("OpenSocial.Dashboard")
…
## Get all viewer apps
#set($sql = ", BaseObject obj, StringProperty prop where doc.fullName=obj.name and obj.className='OpenSocialApplication.ApplicationClass' and prop.id.id=obj.id and prop.name='userId' and prop.value='$context.user' order by doc.date desc")
…
<div id="layout-root" class="gadgets-layout-root"></div><script>
   … 
  document.observe('xwiki:dom:loaded', function() { init(myapps); renderGadgets(); });
</script>

There is a JSX object attached to the page, which defines a class XWikiDashboardGadget extending gadgets.IfrGadget. The new class adds functionalities to default IfrGadget, like gadget maximize handler (to canvas view), changes the content of the gadget box title and adds new fields (e.g. fullAppUrl). The other class gadgets.XWikiUserPrefStore (extends gadgets.UserPrefStore) handles persistent data storage for the User Preferences of each application and user. The UserPrefs are saved as OpenSocial.UserPrefClass objects.

/** XWiki Ifr Dashboard Gadget **/
XWikiDashboardGadget = function(opt_params) {
  gadgets.IfrGadget.call(this, opt_params);
};

XWikiDashboardGadget.inherits(gadgets.IfrGadget);

XWikiDashboardGadget.prototype.handleMaximize = function() { window.location = this.fullAppUrl; };

XWikiDashboardGadget.prototype.getTitleBarContent = function(continuation) { continuation('<div id="' + this.cssClassTitleBar + '-' + this.id + '" class="' + this.cssClassTitleBar + '"><span id="' + this.getIframeId() + '_title" class="' + this.cssClassTitle + '">' + (this.title ? this.title : 'Title') + '</span> | <span class="' + this.cssClassTitleButtonBar + '"><a href="#" onclick="gadgets.container.getGadget(' + this.id + ').handleOpenUserPrefsDialog();return false;" class="' + this.cssClassTitleButton + '">settings</a> <a href="#" onclick="gadgets.container.getGadget(' + this.id + ').handleToggle();return false;" class="' + this.cssClassTitleButton + '">toggle</a> <a href="#" onclick="gadgets.container.getGadget(' + this.id + ').handleMaximize();return false;" class="' + this.cssClassTitleButton + '">see full app</a></span></div>'); };

gadgets.container.gadgetClass = XWikiDashboardGadget;

/** XWiki persistent UserPrefStore **/ gadgets.XWikiUserPrefStore = function() { gadgets.UserPrefStore.call(this); };

gadgets.XWikiUserPrefStore.inherits(gadgets.UserPrefStore);

gadgets.XWikiUserPrefStore.prototype.savePrefs = function(gadget) { var pairs = []; for (var name in gadget.getUserPrefs()) { var value = gadget.getUserPref(name); var pair = encodeURIComponent(name) + '=' + encodeURIComponent(value); pairs.push(pair); } var params = pairs.join('&'); // store user prefs parameters var url = gadget.fullAppUrl + "?xpage=saveuserprefs" + "&" + "params=" + encodeURIComponent(params); new Ajax.Request(url, { method: 'get', onSuccess: savePrefsAjaxSuccess }); };

gadgets.XWikiUserPrefStore.prototype.getPrefs = function(gadget) { var userPrefs = {}; var url = gadget.fullAppUrl + "?xpage=getuserprefs"; new Ajax.Request(url, { method: 'get', onSuccess: getPrefsAjaxSuccess }); return userPrefs; };

gadgets.Container.prototype.userPrefStore = new gadgets.XWikiUserPrefStore();

/** Initialize XWiki Dashboard Container **/ function init(apps) { gadgets.container.layoutManager = new gadgets.FloatLeftLayoutManager('layout-root'); for (var specUrl in apps) { gadgets.container.addGadget(gadgets.container.createGadget({specUrl: specUrl, title: apps[specUrl].title, fullAppUrl: apps[specUrl].fullAppUrl})); } };

/** Render all gadgets on Dashboard **/ function renderGadgets() { gadgets.container.renderGadgets(); };

Links to Edit applications page and Directory (to Add more apps) are also present.

  • OpenSocial.Stylesheet - a bit of CSS
  • OpenSocial.TestingGadgetsSource - used to attach gadgets XML files to the page. Their URLs can be used when adding applications to the Directory
  • OpenSocial.UserPrefClass - stores User Preferences for each application and user in the form of key-value pais
  • OpenSocial.UserPrefClassSheet - default content
  • OpenSocial.UserPrefClassTemplate - default content
  • OpenSocialAppInfo.AppInfoClass - Defines an application from the Directory; contains fields like: URL to Gadget XML definition file, name, description (should also contain image and icon URLs, authors, etc.)
  • OpenSocialAppInfo.AppInfoClassSheet - Displays an application from the Directory. You have links to install the application for yourself, or to manage/delete if you already have it installed; You can also see the Friends which have the same application installed.
Fetching friends with the same app (big sql follows :) ):
#set($appId = $doc.fullName)
#set($sql = "select fnp.value from XWikiDocument adoc, XWikiDocument udoc, BaseObject fo, BaseObject ao, StringProperty fnp, StringProperty uidp, StringProperty aidp where adoc.fullName=ao.name and udoc.fullName=fo.name and udoc.fullName='$context.user' and ao.className='OpenSocialApplication.ApplicationClass' and fo.className='XWiki.FriendClass' and uidp.id.id=ao.id and aidp.id.id=ao.id and fnp.id.id=fo.id and uidp.name='userId' and aidp.name='appId' and aidp.value='$appId' and fnp.name='friendName' and fnp.value=uidp.value")
#set($results = $xwiki.search($sql))

  • OpenSocialAppInfo.AppInfoClassTemplate - default content
  • OpenSocialAppInfo.WebHome - Application Directory. Lists all apps in the Directory and provides a form for adding new ones.
  • OpenScocialApplication.ApplicationClass - Defines an installed application; the two properties name the application id (addId) - document full name for the application in the directory (a document with OpenSocialAppInfo.AppInfoClass object attached), and the user id (userId) - user document full name
  • OpenScocialApplication.ApplicationClassSheet - Renders the application in Canvas view format. Like OpenSocial.Dashboard, includes the Shindig JS files, but renders only 1 gadget this time, and in the canvas format. This gadget is of type XWikiCanvasGadget (extends gadgets.IfrGadget) and is defined in a JSX object attached to the document.
XWikiCanvasGadget = function(opt_params) {
  gadgets.IfrGadget.call(this, opt_params);
};

XWikiCanvasGadget.inherits(gadgets.IfrGadget);

XWikiCanvasGadget.prototype.getTitleBarContent = function(continuation) { continuation('');};

XWikiCanvasGadget.prototype.getUserPrefsDialogContent = function(continuation) { continuation('');};

gadgets.container.gadgetClass = XWikiCanvasGadget;

function canvasRenderGadget(specUrlVal) { var app = gadgets.container.createGadget({specUrl: specUrlVal, width: "100%", height: "600"}); gadgets.container.setView("canvas"); gadgets.container.addGadget(app); gadgets.container.layoutManager.setGadgetChromeIds(['gadget-chrome']); gadgets.container.renderGadget(app); }

  • OpenScocialApplication.ApplicationClassTemplate - default content
  • OpenScocialApplication.MyApps - Lists all installed applications, with buttons to manage/remove. Also there is a button to Add more apps.
  • Panels.MyApps - Panel, displays the newest installed apps (max 5) for the currently logged in user; links to dashboard, edit apps, directory
  • Panels.MyFriends - Panel, displays the friends (max 4) with profile picture of the currently logged in user; links to Profile page for whole list
  • Panels.Navigation - Added the 2 panels
  • XWiki.FriendClass - A friend; objects of this are attached to user profiles; they have a single property friendName, which contains the friends' document full name
  • XWiki.FriendClassSheet - Uses a livetable to display/add friends
  • XWiki.FriendClassTemplate - default content
  • XWiki.MyResources
  • XWiki.XWikiPreferences - Modified
  • XWiki.XWikiUserSheet - Modified to include listing of friends (XWiki.FriendClassSheet) and list applications

xwiki-social-opensocial module

Implements Shindig services and connects Shindig to XWiki's datastore. The implementation is based on the DocumentAccessBridge component, which provides access to data on XWiki.

The implementation is still in an incipient phase, as the registration to XWiki's Component Manager didn't work out as expected. The conflict emerges from the fact that the 4 services (PersonServiceXW, ActivityServiceXW, MessageServiceXW, PersonServiceXW etc.) are instantiated both with Guice for Sindig and by XWiki's Component Manager. For more information, see discussion here: http://markmail.org/thread/zxlnu7q67fxzrjmk

Module details

Packages and Classes:

  • org.xwiki.opensocial.social
    • XWSocialModule.java
  • org.xwiki.opensocial.social.model
    • AddressXW.java
    • NameXW.java
    • PersonXW.java
    • PersonXWComparator.java
  • org.xwiki.opensocial.social.oauth
    • SocialServiceComponent.java - XWiki Component Role, implemented by ActivityServiceXW, AppDataServiceXW, MessageServiceXW, PersonServiceXW in order to gain access to the DocumentAccessBridge component and fetch/add/delete data
  • org.xwiki.opensocial.social.spi.internal
    • ActivityServiceXW.java
    • AppDataServiceXW.java
    • MessageServiceXW.java
    • PersonServiceXW.java - Implements Shindig's PersonService, which fetches people from the datastore

XOO Progress

Hi all!

You are probably curious about the XOO status. Well I will begin to present the functionalities with screenshots, after that the known issues and future development.

NOTE : I apologize to the Windows Users. Unfortunately the extension is not very user friendly because the navigation panel loses every time the focus and the user has to press the navigation panel button again or to minimize the window in order to work easy. This issue appears only for Windows.I've mention at the known issues section details about the Navigation Panel problem. Of course the functionalities work for Windows too, but this issue makes the experience not very pleasant.

XOO functionalities

XOO installation

XOO can be installed in OpenOffice using Extension Manager ExtensionManager.png

XOO toolbar and menu

After you install XOO, you will notice a new Toolbar and a new Menu Option (XWiki). The user takes advantage of the XOO functionalities through this elements ( Toolbar buttons and Submenu options). When the mouse is over one of the toolbar buttons, there is a help text that specifies the button functionality.

XOO.png

Login

Login.png

If the user has customized the XE installation, he/she has to specify the wiki relative path to the server and the XML-RPC relative path. The default values are "/xwiki" and "/xmlrpc"

Custom.png

Navigational panel

The user can visualize the structure of the XWiki server, using the navigational panel. With this one there are some problems,but I will talk about them at the known issue section.

navigation.png


Edit a page

The user can edit with OpenOffice an existing page selecting the page in the navigation panel and using "Edit page button"

edit.png

The XWiki Syntax is transformed in XHTML. If the page contains images that are attached to the current page or to another page, the images are downloaded locally and the user sees them when he edits the page.

ImgSimple.png

When the user edits a page, can include also other images from the local machine.

FromFile.png

These images will become attachments for the current page, if the page will be publish to the server.

Publish a page

After the user edits an existing page, he can publish it using the "Publish button".

publish.png

Any other HTML created or opened with OpenOffice can be published. In this case, the user is requested to specify the name of the page and the space. where the current page will be published.

publishhtml.png

If the page contains pictures, these one become attachment for the page. Currently this operation is not optimal. All the pictures are sent to the server not only the modified ones.

View a page from the server using the default browser

Viewinbrowserbutton.png

Add a new page to the XWiki Server

NewPage.png

Add a new space to the XWiki Server

NewSpace.png

Attach the current document to an XWiki page

The user can attached an opened OO Writer file, to an existing XWiki page, after he/she selects in the navigation panel the page that will be the parent.

Upload.png

Download attachments

The attachments can be downloaded to the local machine.

DownloadButton.png

The user has to specify the location where the attachment will be downloaded.

SaveLoc.png

Known Issues

My first big issue was the Navigational Panel.The ideal one should be a docking window for each opened document. Currently , it is only one instance in the whole extension which is of course not the happiest approach. I read the developers guide from OpenOffice, I tried different "solutions" but none worked. On the OO developers list after 3 weeks of mailing I've received the answer:

"Hi Christina,

Sorry for the late answer but I have tried to look for a solution. Unfortunately I wasn't able to find anything what can help you here. The object you get via the DialogProvider service just implements XDialog and XTopWindow neither implements anything that you need. I fear that your workaround is currently the best available solution. Please write a request for enhancement and the owner to cd@openoffice.org. I hope that we can extend the implementation to support your use case."


Fortunately, today I've received a mail form another developer that gave to me some hints to implement it. Not as docking window, as modal -less (so it is now) but handling the events. We have to decide if we change the design or I should try (it is some work to do) to implement this way. If you want to read the email thread I was talking about you can find it here: http://www.nabble.com/DockingWindows-Java-ts24754063.html

There are more issues and I registered them in Jira. http://jira.xwiki.org/jira/browse/XSANDBOX/component/10799 Feel free to add more.

OpenOffice API development

I'm sorry to write that, but the API from OpenOffice was much more tricky as I've expected. It is not well documented, many things are missing (docking windows, complete open folder control, an easy way to get the extension path etc) . For example, I didn't expected to add an icon at a button to be a big deal. Well I was surprised that OO doesn't accept relative path, only absolute URL, so I had to get the extension path. The solution suggested by OpenOffice.org was to write a configuration file (to be recognized this file should have a defined schema too), in that file to set a property with the value "%origin%" which is a macro that contains the current path. After that, from java code, I had to read this file and call the MacroExpander to get the real value. It's incredible that I waste a lot of time with that small window for the navigation and the problem still persists :-|

Future development

The next things to do are to find solve the navigation panel problem, add support for all the documents with macros, add some progress bars and find a way to minimize the time to get the XWiki server structure , solve the openoffice style problems and so on.

I'm looking forward for your feedback on my project!

Executable

You can find an executable with my extension attached here

If you can't download it, you can find a link here

Screenshots

My Friends Panel

Displays maximum 4 friends of the currently logged in user
Picture17.png

My Apps Panel

Displays most recent 5 installed applications by the currently logged in user
Picture18.png

Edit Applications

You can manage your installed applications: edit app settings or remove
Picture19.png

Application Directory

You can browse the directory and install any application available. If not, you can add new applications to the directory by providing the XML URL for the Application/Gadget
Picture20.png

Application Info Page

Presents information about a certain Gadget/Application in the Directory. You can install it (if you don't already have it installed or edit/remove it if you have it installed). The page also displays which of your friends has it installed
Picture21.png

Dashboard

Provides access to all installed gadgets/apps in default/profile view format
Picture22.png

Application Canvas view

Application page for canvas view. You can also see the installed applications of your friends (the information inside will be displayed as for a simple viewer, and not the owner)
Picture23.png

User Profile

Added lists of friends and applications to profile
Picture26.png

Aug 21 2009

A first version of XWiki Firefox extension


Hi.

A first version of XWiki Firefox extension (or simpler XWikiFox) is now available. To begin, please install the extension from here (you can also find the xpi in the attachments), then you should see a small XWiki icon on the Firefox status bar. Now you need to setup the preferences:

prefs1.jpg

Next, you'll need to add a wiki, in order to get information from that wiki…

prefs2.jpg     prefs3.jpg

The REST url is used to make ajax calls to retrieve data and the Main url is used to retrieve data from rss feeds. If you are using the watchlist functionality on the wiki and are following some specific documents and spaces, then you should also add your username from that wiki.

By now, your data should be loaded, so let's see how the extension is organised:

spaces.jpg


You can view all the spaces from the wiki and dynamically load the documents from a space. Clicking on a space/document will open a new tab with the url of that space/document.

spaces2.jpg

The tags from the wiki are displayed in a nice tag cloud, but for each tag an ajax call is made.. so it is necessary to improve the RESTful API.

tags.jpg

You can also see the recent changes from the wiki:

recent.jpg


If you've filled the username field when you added the wiki, then you can see the recent changes of your watchlist:

watchlist.jpg

The search funcionality is still not fully functional because of the current API limitations.. The search results are displayed in a tree, but you cannot open the urls of the pages in the results.

search.jpg

XWikiFox supports multiple wikis, you can add up to 5 wikis, changing between wikis is easy:

changewiki.jpg

Future improvements:

  • Improve the REST API: in order to get a better performance for the tag cloud, get more information (like the users avatars) for the recent changes and having the ability to go from the search results on the pages urls.
  • Add persistent storage of the wiki state: this needs to be done in order to add notifications to XWikiFox. Mozilla offers a storage service based on the SQLite database, but some serious refactoring is required and writing of some  XPCOM components.
  • Add notifications for any changes in the wiki.
  • Improve the usability: by adding tooltips and other things, this also depends on improving the RESTful API.

Aug 02 2009

Lazy Retrieval of Pages in Navigator

Feature implemented.

This one was tricky!

The objective was to make the xeclipse handle a large wiki, wrt the navigator, of the range of 1000+ pages in a space. Previously, while expanding the node of space, the UI was blocked and went into an unresponsive stage, and came back/became responsive after all the tree was loaded.

Now, the current implementation does this.

  • Creates a Job that asynchronously gets/updates the tree every 200msec.
  • Creates a Job that fetches the nodes in batches [of 20] and adds to the Tree
  • Creates a pending node at the end of the tree, which is removed once when job 2 completes.

The 2nd Job uses the getPages(spaceKey,start,limit) newly created xmlrpc method.

Now, the tree loading is done as a Job, and hence does not block the UI. The scrollbar is not perfect always, because the pages are added over time.

Other actions, opening pages, expanding other nodes, can be done, while the lazy retrieval is taking place.

Jul 05 2009

XOO Status

Hi!

In this post I invite you to test the small XOO. Your feedback is very important to me.

Features till now:

  1. To build the project, it is not necessary to have OpenOffice SDK installed. Just run
    mvn install
  2. To install the extension
    Open Office 3.0 -> Tools -> Extension Manager -> add (the zip output); Restart OpenOffice
If you don't want to build the project and see the first three features, install the Extension attached to this post.

The next step is to create a complete GUI for editing and publishing a page.

Jun 25 2009

Drag and Drop

Drag and Drop

Updated
Possibilites:

1.
  1. Drag and move Attachment -> Drop on some other Page (Of same space/ other space) If the space is not expanded previously, then should expand and show pages. Should Deny Drop on Space/attachment/embedded objects. Name is retained. rpc.moveAttachment is used. No need to expand pages, when hovered over with attachment. The Spaces/pages should be refreshed Accordingly, new notification instance (MOVE_ATTACHMENT)
  2. Drag and move Page -> Drop it on another Space. Name is retained. rpc.movePage is used. Deny Drop on other pages/attachments/objects. No Need to expand spaces/pages when hovered over. The spaces/pages should be refreshed accordingly, new notification instance (MOVE_PAGE). Drag under effects of Feeback_insert_after.. etc is not required.
  3. No Drag/Drop for spaces/objects. (Drop_NONE)
  4. Copy of Attachments. If Drop_copy specified, by key trigger. Almost as same as 1st point above, only use rpc.copyAttachment. If copy to same page, then newfileName should be "Copy of "+oldfileName
  5. Copy of Page. Same as second point. rpc.copyPage used. If copy to same Space, then the newPageId should be (space).Copyof(oldpageID). There is some XMLRPC Bug with the implementation.

TBD: In all these cases, One DataManager to another DataManager DND should not be allowed, obviously.

Features to be created.
  1. DND of Pages between Spaces (That should automatically dnd their corresponding attachments also)
  2. DND of Attachment between pages.
  3. Automatic expansion of (+) spaces/attachment on drag action.
  4. Preventing illegal dnd's
  5. Drag and Drop Between with cnf and Editor (will have to see if possible)

TBD
  1. Creation of renameAttachment xmlrpc function, and a better renamePage() function. -DONE
  2. Creation of a generic XWikiModelObjectTransfer for handling TransferTypes. - Not Required for CNF
  3. Creation of DND sources and targets DONE
  4. Creation of feedbacks, UI features, intuitive elements. DONE


Anything else that you would think is necessary? :)

Jun 24 2009

Bidirectional Converter

Hi!

In this post I will talk about how I implemented the Bidirectional Converter for my extension.

I've used the existing code from the XWiki platform rendering module. In order to be able to do this, I've created a new instance of EmbeddableComponentManager . This object is initialized just once in the whole extension, in the XWikiExtension class.

xwiki 2.0 syntax -> xhtml

  • I've used a Parser for XWiki 2.0 syntax. The result is the a XDOM structure
  • I've applied transformation on the XDom object, for the macros
  • I've used a Renderer for XHTML.
xhtml -> xwiki 2.0 syntax

  • I've used a Parser for xhtml syntax. The result is the a XDOM structure
  • I've used a Renderer for XWiki 2.0 syntax.
For now, the user is able to open with OpenOffice an existing page from the XWiki Server. In order to be able to publish the page at the server, I need to clean up the html generated with OO and after that to apply the Converter. For the Cleaner I would like to use filters used for The OpenOfficeImporter module.

Jun 18 2009

New features

Hi!

It's been a while since my last post, and I apologize for that. Consequently, this post will be longer than the usual ones, and I will talk about what I have done recently.

First of all, not it is easier to build the project (run just mvn install). For more details, please read the README file associated with the project. I've also attached at this post a version of XOO. In order to log in you should provide the complete URL of the server (for example if you want to connect to the local XWiki server you can try url: http://localhost/xwiki/xmlrpc~~ , username ~~Admin, password admin. After you are logged in, you can see the structure of the XWiki server choosing Menu->XWiki->Navigation Panel. Right click on a page name and OpenOffice will open the html page (the conversion in xhtml isn't ready yet, and that's why you will see the syntax of the page , not interpreted).

So let's talk about the components:

  • The navigational panel . Here I had a problem. I wanted something similar with the custom control from XWord, but I didn't manage to find a solution. So for now, I thought to have a dialog with the tree structure. By default, the OpenOffice dialogs are modal. That means, the focus is on the dialog, and the user cannot do something else until he closes the dialog. I needed of course a non-modal dialog. Unfortunately, there was very few documentation about how to do it, so I wasted some time. The solution I've implemented is this one: create a new window with the desktop as parent and display the dialog provided by the dialogProvider Service in this window. In this case, the user can also edit a text and having the navigational panel on the screen. I will paste here some code, maybe it is useful for somebody who has the same problem.

obj = xMCF.createInstanceWithContext("com.sun.star.awt.DialogProvider2", m_xContext); XDialogProvider2 xDialogProvider = (XDialogProvider2) UnoRuntime.queryInterface(XDialogProvider2.class, obj); XDialog xDialog = xDialogProvider.createDialogWithHandler(DialogURL, this);

XControl dialogControl = (XControl) UnoRuntime.queryInterface(XControl.class, xDialog); XControlModel xBasicDialogModel = dialogControl.getModel();

Object dialog = xMCF.createInstanceWithContext("com.sun.star.awt.UnoControlDialog", m_xContext); XControl xControl = (XControl) UnoRuntime.queryInterface(XControl.class, dialog); xControl.setModel(xBasicDialogModel);

XToolkit xToolkit = (XToolkit) UnoRuntime.queryInterface(XToolkit.class, xMCF.createInstanceWithContext( "com.sun.star.awt.Toolkit", m_xContext));

WindowDescriptor aDescriptor = new WindowDescriptor(); aDescriptor.Type = WindowClass.TOP; aDescriptor.WindowServiceName = ""; aDescriptor.ParentIndex = -1; aDescriptor.Parent = xToolkit.getDesktopWindow();

aDescriptor.WindowAttributes = WindowAttribute.BORDER | WindowAttribute.MOVEABLE | WindowAttribute.SIZEABLE | WindowAttribute.CLOSEABLE;

XWindowPeer xPeer = xToolkit.createWindow(aDescriptor);

XWindow xWindow = (XWindow) UnoRuntime.queryInterface(XWindow.class, xPeer); xWindow.setVisible(false); xControl.createPeer(xToolkit, xPeer);

m_xDialog = (XDialog) UnoRuntime.queryInterface(XDialog.class, dialog); m_xControlContainer = (XControlContainer) UnoRuntime.queryInterface(XControlContainer.class, m_xDialog);

The navigational panel is not in the right place,for now. I will do more research about another way to implement this control. If the dialog remains the only choice then some coordinates should be calculated.

  • File storage. In order to edit, create a new page and publish a new one, I create some temporal files that stores the information. So for every page I create a folder in the default java temp folder. This folder will contain the page itself in html and the objects associated with the page (images for example). In this scope, I've created a class that handles all the work with temporal files.


  • Opening a html file from OpenOffice. OpenOffice works only with URLs, so I had to convert the file's path in a url using XFileIdentifierConverter interface


Jun 14 2009

Starting GWT with Maven

I have started studying GWT. I started reading ebook GWT in Practice. It helped me to quickly understand the basics of a GWT Project and Then I looked for how we could create and build a GWT project with Maven. Here are some important points to create a GWT maven project.

  • Download and install maven google web toolkit archetype. Download maven-googlewebtoolkit2-archetype-1.0.4.jar file from this link. GWT-Maven Archetype
  • Install the downloaded maven archetype
mvn install:install-file \
   -DgroupId=com.totsp.gwt \
   -DartifactId=maven-googlewebtoolkit2-archetype \
   -Dversion=1.0.4 \
   -Dpackaging=jar 
   -Dfile=path/to/downloaded/jar/file/maven-googlewebtoolkit2-archetype-1.0.4.jar

  • Now you can create the maven GWT project with the following command running in terminal
mvn archetype:create \
   -DarchetypeGroupId=com.totsp.gwt \
   -DarchetypeArtifactId=maven-googlewebtoolkit2-archetype \
   -DarchetypeVersion=1.0.4 \
   -DgroupId=myGroupId \
   -DartifactId=myArtifactId

  • After all this, you can run your GWT project in hosted mode and take all GWT advantages using following command
mvn gwt-maven:gwt

  • Or you can build a WAR file using this.
mvn clean gwt-maven install

Jun 04 2009

Introduction

  • Title: XWiki Widget and Firefox extension
  • Objective: The objective of this project is to make relevant information from a wiki accessible in a widget.
  • Student: Alexandru Cismaru
  • Contact: alex.cismaru@gmail.com

 Project Description:

The world has seen an explosion in the use of widgets over the past year or so, and it's time for XWiki to have it's own web and desktop widgets.

User Experience The most important thing in this project is, in my opinion, the user experience. If the users don't experience quality throughout the widget, they may conclude there is a lack of quality everywhere. This means we need to pay attention to the quality of icons, images, text, background, and interaction. Each of these elements is equally important (maybe only the data is more important).

Fresh Data. The widget should display only information that changes often, information that is static for more than a day makes a widget dull. A user looks to a widget to see interesting things that are active.

Choosing the information relevant to individual users. I think a tabbed interface is the best choice for the user interface, with three tabs: General, Watchlist and Search. The General tab will display general information of a wiki: the most recent modifications, the spaces and the tags. Widgets are all about user choice and preference. That's why I propose to have a tab with the information from the Watchlist and offering the possibility to add his own rss feeds. I also think a search tab that will display a list of results is useful.

Interface design. We need to keep the widget simple and aesthetically pleasing, to show only relevant information. I want to use icons, images, and signs as much as possible; they give visual clues of the functionality. The design of the widget should not be too obtrusive. The use of buttons and user controls should be avoided at all costs (that's why I preferred using links for refresh and logout actions instead of buttons) .

Design Patterns. Developing a widget is like developing any other  software product, so we must have some design patterns to follow in order to make development easier. My approach is to concentrate on: maintainability, customizability and extensibility. By making a good separation of modules, and writing reusable code helps to maintain the widget and makes it easier to add new features. Because we want to release a XWiki widget on as many platforms as possible, I think it's important to make the widget easy to be customized for a specific platform. Another desired trait of the widget is extensibility, this way the widget can be used to extend existing functionalities.

Jun 01 2009

Creating a wizard for connecting to an XWiki server

Hi!

Finally, I've implemented a first feature for the XOO project : the wizard for connecting to a XWiki server

In order to achieve this goal, I've created the following classes

  • XWikiDialog.java - this class is the base class for all the Dialogs that I need in the application. It contains methods like create a new Dialog , get the set of the properties of a control from the dialog, dispose the dialog. It was necessary to create this kind of class because in the OpenOffice API is not simple to create a dialog. (I have to use the DialogProvider service which gives the dialog created with the basic editor using the URL parameter).

  • SettingsDialog.java - this class extends the XWikiDialog and represents the Dialog which appears when the user wants to change the connection settings. For now, it has only 3 fields for the server url, username and password

  • Settings.java - this class contains all the settings made by the user. For now it has only 3 attributes (server url, username and password). It can be more generic if I use a dictionary structure instead of all those attributes

  • Utils.java - this class displays useful messages for the user (like the error messagebox when there cannot be established a connection with the XWiki server).

  • XWikiAddIn.java - a singleton which contains the XWiki stucture, the XMLRPCClient and the settings.

  • Debug.java - a singleton used for displaying messages for debugging

  • IConstants.java - an interfaces with all the constants from the project. I find this interface  useful especially for the localization.

Besides this classes, I've also created a BASIC dialogs library which contains for the moment only the dialog for the connection settings. To include this, I've modified the dep.xml file and the META-INF/manifest.mf

Next step .. A navigation panel for browsing the documents inside the wiki!!

May 28 2009

Creating Aggregator pom.xml

After setting up the maven project, pom.xml file should be aggregated. If you havent set up the maven project yet, refer Setting Up the Project with Maven by Anamaria Stoica.

For better understanding of pom.xml, refer Maven Pom Reference, Introduction-to-the-pom .

Import Export from any Wiki Project Structure :

.
 |-- xwiki-application-importer
 |   `-- pom.xml
 |
 |-- xwiki-core-importer
 |   `-- pom.xml
 |
 `-- pom.xml

I have followed these steps to aggregate pom.xml:

*. Add the Copyright info. 
Get it from : http://svn.xwiki.org/svnroot/xwiki/platform/trunks/pom.xml

*. Editing the pom in the sub-modules.

<parent>
    <groupId>com.xpn.xwiki.platform.applications</groupId>
    <artifactId>xwiki-applications</artifactId>
    <version>21-SNAPSHOT</version>
  </parent>
  <artifactId>xwiki-application-importer</artifactId>
  <packaging>xar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>xwiki-application-importer</name>
  <description>Application - import from other wikis.</description>

*. Editing the pom in the main module.

<groupId>org.xwiki.platform</groupId>
  <artifactId>importexport</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>importexport</name>
  <modules>
    <module>xwiki-application-importer</module>
    <module>xwiki-core-importer</module>
  </modules>


That Ends Aggregating pom.xml.

May 27 2009

How to build and install XOO

Hi!

If you want to build and install the XOO project, you have to follow this steps:

  1. Download and install OpenOffice.org 3. from http://www.openoffice.org/
  2. Download and install OpenOffice SDK 3. from http://download.openoffice.org/3.1.0/sdk.html . A useful link is also : http://wiki.services.openoffice.org/wiki/SDKInstallation. If you want to be sure that the installation worked, try to build one of the examples from the SDK folder. In order to be able to run an example you have to set the environment variables for the SDK. (Run one of the setsdkenv script)
  3. Download the CVS project http://api.openoffice.org/source/browse/api/maven2integration/ and run mvn install in order to install the maven open office plugin in the local repository
  4. Enter in the root folder of the XOO project and run
    mvn assembly:assembly -Dooo=/path/to/OpenOffice.org_installation -Dooosdk=/path/to/OOSDK
    ex: mvn assembly:assembly -Dooo=/home/kristina/opt/openoffice.org3 -Dooosdk=/opt/openoffice.org/basis3.0/sdk
  5. In the target folder there is an archive xoo-1.0-bin.zip. This is the extension. In order to install it run:
    $ unopkg add --shared xoo-1.0-bin.zip
    Another method to install the extension is:
    OppenOffice.org Writer -> Tools -> Extension Manager -> Add -> Browse to the path of the zip file xoo-1.0-bin.zip
    Restart the Writer.
    ; A new menu XWiki should be enabled.
If you want to clean up: mvn clean

Soon will be added also tests. If tou want to run only the tests: mvn test

Tags:
Created by Administrator on 2005/01/28 16:50
Last modified by Sergiu Dumitriu on 2009/04/28 23:51

Workstream


This wiki is licensed under a Creative Commons 2.0 license
XWiki Enterprise 2.3-SNAPSHOT.27632 - Documentation